Merge branch 'feature/ceilometerDashboard' into develop
diff --git a/xos/configurations/bash/Makefile b/xos/configurations/bash/Makefile
index f33ea56..a668a55 100644
--- a/xos/configurations/bash/Makefile
+++ b/xos/configurations/bash/Makefile
@@ -1,6 +1,8 @@
MYIP:=$(shell hostname -i)
test: common_cloudlab
+ rm ../../xos_configuration/*
+ cp ../common/xos_common_config ../../xos_configuration/
cat ../common/Dockerfile.common Dockerfile.bash > Dockerfile
cd ../../..; sudo docker build -t xos -f xos/configurations/bash/Dockerfile .
sudo docker run -i --tty --add-host="ctl:$(MYIP)" -p 9999:8000 xos
diff --git a/xos/configurations/cord/Makefile b/xos/configurations/cord/Makefile
index 7714d2a..ef823cd 100644
--- a/xos/configurations/cord/Makefile
+++ b/xos/configurations/cord/Makefile
@@ -3,11 +3,11 @@
LAST_CONTAINER=$(shell sudo docker ps -l -q)
cord: common_cloudlab ceilometer_dashboard virtualbng_json
- rm ../../xos/xos_configuration/*
+ rm ../../xos_configuration/*
echo "# Autogenerated -- do not edit" > Dockerfile
cat ../common/Dockerfile.common Dockerfile.cord >> Dockerfile
- cp ../common/xos_common_config ../../xos/xos_configuration/
- cp ./xos_cord_config ../../xos/xos_configuration/
+ cp ../common/xos_common_config ../../xos_configuration/
+ cp ./xos_cord_config ../../xos_configuration/
cd ../../..; sudo docker build -t xos -f xos/configurations/cord/Dockerfile .
sudo docker run -d --add-host="ctl:$(MYIP)" -p 9999:8000 xos
bash ../common/wait_for_xos.sh
diff --git a/xos/configurations/cord/ceilometer.yaml b/xos/configurations/cord/ceilometer.yaml
index 73c18db..b64fbef 100644
--- a/xos/configurations/cord/ceilometer.yaml
+++ b/xos/configurations/cord/ceilometer.yaml
@@ -33,19 +33,19 @@
type: tosca.nodes.NetworkTemplate
ceilometer_network:
- type: tosca.nodes.network.Network.XOS
- properties:
- ip_version: 4
- labels: ceilometer_client_access
- requirements:
- - network_template:
- node: Private
- relationship: tosca.relationships.UsesNetworkTemplate
- - owner:
- node: mysite_ceilometer
- relationship: tosca.relationships.MemberOfSlice
- - connection:
- node: mysite_ceilometer
+ type: tosca.nodes.network.Network.XOS
+ properties:
+ ip_version: 4
+ labels: ceilometer_client_access
+ requirements:
+ - network_template:
+ node: Private
+ relationship: tosca.relationships.UsesNetworkTemplate
+ - owner:
+ node: mysite_ceilometer
+ relationship: tosca.relationships.MemberOfSlice
+ - connection:
+ node: mysite_ceilometer
relationship: tosca.relationships.ConnectsToSlice
mysite:
@@ -72,10 +72,8 @@
Ceilometer:
type: tosca.nodes.DashboardView
- properties:
- url: { get_artifact: [ SELF, ceilometer_url, LOCAL_FILE] }
artifacts:
- ceilometer_url: /root/setup/ceilometer_url
+ ceilometer_url: template:xosCeilometerDashboard
Tenant:
type: tosca.nodes.DashboardView
diff --git a/xos/configurations/cord/ceilometer_pub_sub.tar.gz b/xos/configurations/cord/ceilometer_pub_sub.tar.gz
new file mode 100644
index 0000000..eb88a2b
--- /dev/null
+++ b/xos/configurations/cord/ceilometer_pub_sub.tar.gz
Binary files differ
diff --git a/xos/configurations/cord/cord.yaml b/xos/configurations/cord/cord.yaml
index a35454b..5d95d7a 100644
--- a/xos/configurations/cord/cord.yaml
+++ b/xos/configurations/cord/cord.yaml
@@ -203,6 +203,16 @@
node: mysite_vbng
relationship: tosca.relationships.ConnectsToSlice
+ Private-Direct:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ access: direct
+
+ Private-Indirect:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ access: indirect
+
subscriber_network:
type: tosca.nodes.network.Network
properties:
@@ -252,7 +262,7 @@
node: mysite
relationship: tosca.relationships.MemberOfSite
- vcpe_docker_image:
- node: andybavier/docker-vcpe
+ node: docker-vcpe
relationship: tosca.relationships.UsesImage
properties:
default_isolation: container
@@ -419,13 +429,14 @@
relationship: tosca.relationships.MemberOfSlice
# docker image for vcpe containers
- andybavier/docker-vcpe:
+ docker-vcpe:
# TODO: need to attach this to mydeployment
type: tosca.nodes.Image
properties:
kind: container
container_format: na
disk_format: na
+ path: andybavier/docker-vcpe
# A subscriber
My House:
diff --git a/xos/configurations/cord/install_ceilometer_patch.sh b/xos/configurations/cord/install_ceilometer_patch.sh
index d6b4056..77aa05b 100755
--- a/xos/configurations/cord/install_ceilometer_patch.sh
+++ b/xos/configurations/cord/install_ceilometer_patch.sh
@@ -3,9 +3,9 @@
exit 0
fi
echo "Verifying if all the required files are present"
-if [ ! -f openstack_ceilometer_patch.tar.gz ];
+if [ ! -f openstack_ceilometer_patch.tar.gz ] || [ ! -f ceilometer_pub_sub.tar.gz ];
then
- echo "File openstack_ceilometer_patch.tar.gz not found"
+ echo "File openstack_ceilometer_patch.tar.gz or ceilometer_pub_sub.tar.gz not found"
exit 1
fi
echo "Copying the ceilometer patch files to /usr/lib/python2.7/dist-packages/ceilometer"
@@ -20,3 +20,7 @@
sudo service ceilometer-agent-notification restart
echo "Restarting ceilometer-agent-central"
sudo service ceilometer-agent-central restart
+tar -xzf ceilometer_pub_sub.tar.gz
+echo "Starting Ceilometer PUB/SUB service"
+cd ceilometer_pub_sub
+python sub_main.py &
diff --git a/xos/configurations/devel/Makefile b/xos/configurations/devel/Makefile
index f95c4e3..216673d 100644
--- a/xos/configurations/devel/Makefile
+++ b/xos/configurations/devel/Makefile
@@ -7,8 +7,8 @@
devstack: common_devstack xos
xos:
- rm ../../xos/xos_configuration/*
- cp ../common/xos_common_config ../../xos/xos_configuration/
+ rm ../../xos_configuration/*
+ cp ../common/xos_common_config ../../xos_configuration/
echo "# Autogenerated -- do not edit" > Dockerfile
cat ../common/Dockerfile.common Dockerfile.devel >> Dockerfile
cd ../../..; sudo docker build -t xosproject/xos-devel -f xos/configurations/devel/Dockerfile .
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index ae1dbce..e30877a 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -6,20 +6,20 @@
all: frontend
frontend:
- rm ../../xos/xos_configuration/*
+ rm ../../xos_configuration/*
sudo apt-get -y install httpie
cat ../common/Dockerfile.common Dockerfile.frontend > Dockerfile
- cp ../common/xos_common_config ../../xos/xos_configuration/
+ cp ../common/xos_common_config ../../xos_configuration/
cd ../../..; sudo docker build -t xos -f xos/configurations/frontend/Dockerfile .
sudo docker run -v $(XOS_FOLDER)/../../core/xoslib:/opt/xos/core/xoslib -p 9999:8000 --add-host="0.0.0.0:127.0.0.1" xos
bash ../common/wait_for_xos.sh
echo $(RUNNING_CONTAINER)
interactive:
- rm ../../xos/xos_configuration/*
+ rm ../../xos_configuration/*
cat ../common/Dockerfile.common Dockerfile.frontend > Dockerfile
- cp ../common/xos_common_config ../../xos/xos_configuration/
- #cp ../cord/xos_cord_config ../../xos/xos_configuration/
+ cp ../common/xos_common_config ../../xos_configuration/
+ #cp ../cord/xos_cord_config ../../xos_configuration/
cd ../../..; sudo docker build -t xos -f xos/configurations/frontend/Dockerfile .
echo "Inside the container run: /usr/bin/make -C /opt/xos/configurations/frontend -f Makefile.inside"
sudo docker run -it -v $(shell pwd)/../..:/opt/xos -p 9999:8000 --add-host="0.0.0.0:127.0.0.1" xos
diff --git a/xos/core/admin.py b/xos/core/admin.py
index be9dcc0..03f8c83 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1206,7 +1206,7 @@
class ImageAdmin(XOSBaseAdmin):
fieldsets = [('Image Details',
- {'fields': ['backend_status_text', 'name', 'kind', 'disk_format', 'container_format'],
+ {'fields': ['backend_status_text', 'name', 'kind', 'disk_format', 'container_format', 'tag', 'path'],
'classes': ['suit-tab suit-tab-general']})
]
readonly_fields = ('backend_status_text', )
@@ -1215,7 +1215,7 @@
inlines = [InstanceInline, ControllerImagesInline]
- user_readonly_fields = ['name', 'disk_format', 'container_format']
+ user_readonly_fields = ['name', 'disk_format', 'container_format', 'tag', 'path']
list_display = ['backend_status_icon', 'name', 'kind']
list_display_links = ('backend_status_icon', 'name', )
@@ -1848,7 +1848,7 @@
user_readonly_inlines = []
inlines = [NetworkParameterInline,]
fieldsets = [
- (None, {'fields': ['name', 'description', 'guaranteed_bandwidth', 'visibility', 'translation', 'shared_network_name', 'shared_network_id', 'topology_kind', 'controller_kind'],
+ (None, {'fields': ['name', 'description', 'guaranteed_bandwidth', 'visibility', 'translation', 'access', 'shared_network_name', 'shared_network_id', 'topology_kind', 'controller_kind'],
'classes':['suit-tab suit-tab-general']}),]
suit_form_tabs = (('general','Network Template Details'), ('netparams', 'Parameters') )
diff --git a/xos/core/models/image.py b/xos/core/models/image.py
index 1a3cbf7..69d0f03 100644
--- a/xos/core/models/image.py
+++ b/xos/core/models/image.py
@@ -16,6 +16,8 @@
path = StrippedCharField(max_length=256, null=True, blank=True, help_text="Path to image on local disk")
deployments = models.ManyToManyField('Deployment', through='ImageDeployments', blank=True, help_text="Select which images should be instantiated on this deployment", related_name='images')
+ tag = StrippedCharField(max_length=256, null=True, blank=True, help_text="For Docker Images, tag of image")
+
def __unicode__(self): return u'%s' % (self.name)
class ImageDeployments(PlCoreBase):
diff --git a/xos/core/models/network.py b/xos/core/models/network.py
index 6894f9f..a019091 100644
--- a/xos/core/models/network.py
+++ b/xos/core/models/network.py
@@ -100,15 +100,17 @@
TRANSLATION_CHOICES = (('none', 'none'), ('NAT', 'NAT'))
TOPOLOGY_CHOICES = (('bigswitch', 'BigSwitch'), ('physical', 'Physical'), ('custom', 'Custom'))
CONTROLLER_CHOICES = ((None, 'None'), ('onos', 'ONOS'), ('custom', 'Custom'))
+ ACCESS_CHOICES = ((None, 'None'), ('indirect', 'Indirect'), ('direct', 'Direct'))
name = models.CharField(max_length=32)
description = models.CharField(max_length=1024, blank=True, null=True)
guaranteed_bandwidth = models.IntegerField(default=0)
visibility = models.CharField(max_length=30, choices=VISIBILITY_CHOICES, default="private")
translation = models.CharField(max_length=30, choices=TRANSLATION_CHOICES, default="none")
+ access = models.CharField(max_length=30, null=True, blank=True, choices=ACCESS_CHOICES, help_text="Advertise this network as a means for other slices to contact this slice")
shared_network_name = models.CharField(max_length=30, blank=True, null=True)
shared_network_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum network")
- topology_kind = models.CharField(null=False, blank=False, max_length=30, choices=TOPOLOGY_CHOICES, default="BigSwitch")
+ topology_kind = models.CharField(null=False, blank=False, max_length=30, choices=TOPOLOGY_CHOICES, default="bigswitch")
controller_kind = models.CharField(null=True, blank=True, max_length=30, choices=CONTROLLER_CHOICES, default=None)
def __init__(self, *args, **kwargs):
@@ -126,6 +128,10 @@
print >> sys.stderr, "XXX warning: topology_kind invalid case"
self.toplogy_kind="custom"
+ def save(self, *args, **kwargs):
+ self.enforce_choices(self.access, self.ACCESS_CHOICES)
+ super(NetworkTemplate, self).save(*args, **kwargs)
+
def __unicode__(self): return u'%s' % (self.name)
class Network(PlCoreBase, ParameterMixin):
diff --git a/xos/core/models/plcorebase.py b/xos/core/models/plcorebase.py
index 1a2c37c..360792f 100644
--- a/xos/core/models/plcorebase.py
+++ b/xos/core/models/plcorebase.py
@@ -132,6 +132,16 @@
else:
return ("error", html_escape(self.backend_status, quote=True))
+ def enforce_choices(self, field, choices):
+ choices = [x[0] for x in choices]
+ for choice in choices:
+ if field==choice:
+ return
+ if (choice==None) and (field==""):
+ # allow "" and None to be equivalent
+ return
+ raise Exception("Field value %s is not in %s" % (field, str(choices)))
+
class PlCoreBase(models.Model, PlModelMixIn):
objects = PlCoreBaseManager()
deleted_objects = PlCoreBaseDeletionManager()
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index 2b450e0..7cf2a6b 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -168,12 +168,35 @@
# print "add instance", s
+ def get_vtn_src_nets(self):
+ nets=[]
+ for slice in self.slices.all():
+ for ns in slice.networkslices.all():
+ if not ns.network:
+ continue
+ if ns.network.template.access in ["direct", "indirect"]:
+ # skip access networks; we want to use the private network
+ continue
+ if ns.network.name in ["wan_network", "lan_network"]:
+ # we don't want to attach to the vCPE's lan or wan network
+ # we only want to attach to its private network
+ # TODO: fix hard-coding of network name
+ continue
+ for cn in ns.network.controllernetworks.all():
+ if cn.net_id:
+ net = {"name": ns.network.name, "net_id": cn.net_id}
+ nets.append(net)
+ return nets
+
def get_vtn_nets(self):
nets=[]
for slice in self.slices.all():
for ns in slice.networkslices.all():
if not ns.network:
continue
+ if ns.network.template.access not in ["direct", "indirect"]:
+ # skip anything that's not an access network
+ continue
for cn in ns.network.controllernetworks.all():
if cn.net_id:
net = {"name": ns.network.name, "net_id": cn.net_id}
@@ -195,11 +218,11 @@
def get_vtn_dependencies_names(self):
return [x["name"]+"_"+x["net_id"] for x in self.get_vtn_dependencies_nets()]
- def get_vtn_ids(self):
- return [x["net_id"] for x in self.get_vtn_nets()]
+ def get_vtn_src_ids(self):
+ return [x["net_id"] for x in self.get_vtn_src_nets()]
- def get_vtn_names(self):
- return [x["name"]+"_"+x["net_id"] for x in self.get_vtn_nets()]
+ def get_vtn_src_names(self):
+ return [x["name"]+"_"+x["net_id"] for x in self.get_vtn_src_nets()]
class ServiceAttribute(PlCoreBase):
@@ -496,7 +519,7 @@
"trusty-server-multi-nic", # CloudLab
]
- LOOK_FOR_CONTAINER_IMAGES=["andybavier/docker-vcpe"]
+ LOOK_FOR_CONTAINER_IMAGES=["docker-vcpe"]
class Meta:
proxy = True
@@ -576,14 +599,6 @@
raise XOSProgrammingError("No VPCE image (looked for %s)" % str(look_for_images))
- @creator.setter
- def creator(self, value):
- if value:
- value = value.id
- if (value != self.get_attribute("creator_id", None)):
- self.cached_creator=None
- self.set_attribute("creator_id", value)
-
def save_instance(self, instance):
# Override this function to do custom pre-save or post-save processing,
# such as creating ports for containers.
@@ -671,6 +686,11 @@
self.instance.delete()
self.instance = None
+ def save(self, *args, **kwargs):
+ if (not self.creator) and (hasattr(self, "caller")) and (self.caller):
+ self.creator = self.caller
+ super(TenantWithContainer, self).save(*args, **kwargs)
+
class CoarseTenant(Tenant):
""" TODO: rename "CoarseTenant" --> "StaticTenant" """
class Meta:
diff --git a/xos/core/static/xos.css b/xos/core/static/xos.css
index 40cfcc3..685361e 100644
--- a/xos/core/static/xos.css
+++ b/xos/core/static/xos.css
@@ -62,6 +62,7 @@
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
+ background: white;
}
#wrapper.toggled #sidebar-wrapper {
diff --git a/xos/core/xoslib/dashboards/xosCeilometerDashboard.html b/xos/core/xoslib/dashboards/xosCeilometerDashboard.html
index c95d3d3..22511f4 100644
--- a/xos/core/xoslib/dashboards/xosCeilometerDashboard.html
+++ b/xos/core/xoslib/dashboards/xosCeilometerDashboard.html
@@ -3,18 +3,16 @@
<!-- browserSync -->
<!-- inject:css -->
-<link rel="stylesheet" href="/css/ceilometerDashboard.css">
-<link rel="stylesheet" href="/css/dev.css">
+<link rel="stylesheet" href="/../../static/css/xosCeilometerDashboard.css">
<!-- endinject -->
<link rel="stylesheet" href="css/ceilometerDashboard.css">
-
<div id="xosCeilometerDashboard">
- <div ui-view></div>
+ <div ui-view ng-class="stateName"></div>
</div>
+
<!-- inject:js -->
-<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
-<script src="http://cdn.jsdelivr.net/angular.chartjs/latest/angular-chart.min.js"></script>
+<script src="/../../static/js/vendor/xosCeilometerDashboardVendor.js"></script>
<script src="/../../static/js/xosCeilometerDashboard.js"></script>
<!-- endinject -->
diff --git a/xos/core/xoslib/methods/ceilometerview.py b/xos/core/xoslib/methods/ceilometerview.py
index d02e716..5e0ac35 100644
--- a/xos/core/xoslib/methods/ceilometerview.py
+++ b/xos/core/xoslib/methods/ceilometerview.py
@@ -152,6 +152,23 @@
else:
return list(set(a) - set(b))
+def get_resource_map(request, ceilometer_url):
+ resource_map = {}
+ try:
+ resources = resource_list(request, ceilometer_url=ceilometer_url)
+ for r in resources:
+ if 'display_name' in r['metadata']:
+ name = r['metadata']['display_name']
+ elif 'name' in r['metadata']:
+ name = r['metadata']['name']
+ else:
+ name = r['resource_id']
+ resource_map[r['resource_id']] = name
+ except requests.exceptions.RequestException as e:
+ raise e
+
+ return resource_map
+
class Meters(object):
"""Class for listing of available meters.
@@ -163,11 +180,12 @@
"""
- def __init__(self, request=None, ceilometer_meter_list=None, ceilometer_url=None, tenant_map=None):
+ def __init__(self, request=None, ceilometer_meter_list=None, ceilometer_url=None, tenant_map=None, resource_map=None):
# Storing the request.
self._request = request
self.ceilometer_url = ceilometer_url
self.tenant_map = tenant_map
+ self.resource_map = resource_map
# Storing the Ceilometer meter list
if ceilometer_meter_list:
@@ -382,21 +400,23 @@
if meter_info:
label = meter_info["label"]
description = meter_info["description"]
- meter_type = meter_info["type"]
+ meter_category = meter_info["type"]
else:
label = ""
description = ""
- meter_type = "Other"
+ meter_category = "Other"
for meter in meter_candidates:
meter["label"] = label
meter["description"] = description
- meter["type"] = meter_type
+ meter["category"] = meter_category
if meter["project_id"] in self.tenant_map.keys():
meter["slice"] = self.tenant_map[meter["project_id"]]["slice"]
meter["service"] = self.tenant_map[meter["project_id"]]["service"]
else:
meter["slice"] = meter["project_id"]
meter["service"] = "Other"
+ if meter["resource_id"] in self.resource_map.keys():
+ meter["resource_name"] = self.resource_map[meter["resource_id"]]
self._cached_meters[meter_name] = meter_candidates
@@ -929,7 +949,8 @@
if (not tenant_ceilometer_url):
raise XOSMissingField("Tenant ceilometer URL is missing")
tenant_map = getTenantControllerTenantMap(request.user)
- meters = Meters(request, ceilometer_url=tenant_ceilometer_url, tenant_map=tenant_map)
+ resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url)
+ meters = Meters(request, ceilometer_url=tenant_ceilometer_url, tenant_map=tenant_map, resource_map=resource_map)
services = {
_('Nova'): meters.list_nova(),
_('Neutron'): meters.list_neutron(),
@@ -997,7 +1018,8 @@
return Response(row)
#Statistics query for all meter
- meters = Meters(request, ceilometer_url=tenant_ceilometer_url, tenant_map=tenant_map)
+ resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url)
+ meters = Meters(request, ceilometer_url=tenant_ceilometer_url, tenant_map=tenant_map, resource_map=resource_map)
services = {
_('Nova'): meters.list_nova(),
_('Neutron'): meters.list_neutron(),
@@ -1017,11 +1039,13 @@
statistic = statistics[-1]
row = {"name": 'none',
"slice": meter["slice"],
+ "project_id": meter["project_id"],
"service": meter["service"],
"resource_id": meter["resource_id"],
+ "resource_name": meter["resource_name"],
"meter": meter["name"],
"description": meter["description"],
- "type": service,
+ "category": service,
"time": statistic["period_end"],
"value": statistic["avg"],
"unit": meter["unit"]}
@@ -1055,3 +1079,23 @@
samples = sample_list(request, meter_name,
ceilometer_url=tenant_ceilometer_url, query=query, limit=limit)
return Response(samples)
+
+class ServiceAdjustScale(APIView):
+ method_kind = "list"
+ method_name = "serviceadjustscale"
+
+ def get(self, request, format=None):
+ if (not request.user.is_authenticated()) or (not request.user.is_admin()):
+ raise PermissionDenied("You must be authenticated admin user in order to use this API")
+ service = request.QUERY_PARAMS.get('service', None)
+ slice_hint = request.QUERY_PARAMS.get('slice_hint', None)
+ scale = request.QUERY_PARAMS.get('scale', None)
+ if not service or not slice_hint or not scale:
+ raise XOSMissingField("Mandatory fields missing")
+ services = Service.select_by_user(request.user)
+ logger.info('SRIKANTH: Services for this user %(services)s' % {'services':services})
+ if not services or (not services.get(name=service)):
+ raise XOSMissingField("Service not found")
+ service = services.get(name=service)
+ service.adjust_scale(slice_hint, scale)
+ return Response("Success")
diff --git a/xos/core/xoslib/methods/vtn.py b/xos/core/xoslib/methods/vtn.py
index a912613..1a2af53 100644
--- a/xos/core/xoslib/methods/vtn.py
+++ b/xos/core/xoslib/methods/vtn.py
@@ -38,7 +38,7 @@
def get_services_names(self, request, pk=None):
result = {}
for service in Service.objects.all():
- for id in service.get_vtn_names():
+ for id in service.get_vtn_src_names():
dependencies = service.get_vtn_dependencies_names()
if dependencies:
result[id] = dependencies
@@ -47,7 +47,7 @@
def get_services(self, request, pk=None):
result = {}
for service in Service.objects.all():
- for id in service.get_vtn_ids():
+ for id in service.get_vtn_src_ids():
dependencies = service.get_vtn_dependencies_ids()
if dependencies:
result[id] = dependencies
@@ -55,7 +55,7 @@
def get_service(self, request, pk=None, service=None):
for xos_service in Service.objects.all():
- if service in xos_service.get_vtn_ids():
+ if service in xos_service.get_vtn_src_ids():
return Response(xos_service.get_vtn_dependencies_ids())
raise DoesNotExist()
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc b/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc
index c852748..868fd4b 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc
@@ -16,7 +16,7 @@
],
"rules": {
"quotes": [2, "single"],
- "camelcase": [1, {"properties": "always"}],
+ "camelcase": [0, {"properties": "always"}],
"no-underscore-dangle": 1,
"eqeqeq": [2, "smart"],
"no-alert": 1,
@@ -29,6 +29,7 @@
"no-trailing-spaces": [1, { skipBlankLines: true }],
"no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
"new-cap": 0,
+ "no-undef": 2,
//"angular/ng_module_name": [2, '/^xos\.*[a-z]*$/'],
//"angular/ng_controller_name": [2, '/^[a-z].*Ctrl$/'],
@@ -37,6 +38,7 @@
//"angular/ng_di": [0, "function or array"]
},
"globals" :{
- "angular": true
+ "angular": true,
+ "Chart": true
}
}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/bower.json b/xos/core/xoslib/ngXosViews/ceilometerDashboard/bower.json
index c11ad13..363d59d 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/bower.json
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/bower.json
@@ -16,7 +16,8 @@
],
"dependencies": {
"angular-chart.js": "~0.8.7",
- "angular-animate": "~1.4.8"
+ "angular-animate": "~1.4.8",
+ "ui.bootstrap": "~0.14.3"
},
"devDependencies": {
"jquery": "~2.1.4",
@@ -27,5 +28,10 @@
"angular-resource": "~1.4.7",
"ng-lodash": "~0.3.0",
"bootstrap-css": "3.3.4"
+ },
+ "overrides": {
+ "ui.bootstrap": {
+ "main": ["src/accordion/accordion.js", "src/collapse/collapse.js"]
+ }
}
}
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js
index 6dd56e2..8fc0bd5 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js
@@ -7,7 +7,7 @@
// (works only for local environment as both application are served on the same domain)
module.exports = {
- host: 'http://clnode022.clemson.cloudlab.us:9999',
- xoscsrftoken: 'VZxPA6PAYcNhlkZXyxsk4I13pfNWGf0G',
- xossessionid: 'rpqld0c44dv6clhtlwkjt96auwpx8lrb'
+ host: 'http://clnode015.clemson.cloudlab.us:9999/',
+ xoscsrftoken: 'w0qMPZCk8nByQh9Zy86nPs5OM5G5lKdb',
+ xossessionid: 'kvv2aa1il6u4i7j6yu2399r4tdpdeoxz'
};
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/srikanth.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/srikanth.js
index c7b051d..8d76a20 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/srikanth.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/srikanth.js
@@ -8,6 +8,6 @@
module.exports = {
host: 'http://130.127.133.87:9999',
- xoscsrftoken: 'z0Ddap4Cx0v7onhXuqq1cIyp1NbYFUjA',
- xossessionid: 'c93iufpoe8e7vbo6uesrh8j5xnvb6fva'
+ xoscsrftoken: 'Ed51juEvODfN01dtXO7iqRkXDdBIL0sr',
+ xossessionid: 'b3vg7a2qtm7roclcwlqkf7f5xca645jx'
};
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js
index d0d38f9..9f9bfb8 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js
@@ -22,6 +22,10 @@
var inject = require('gulp-inject');
var rename = require('gulp-rename');
var replace = require('gulp-replace');
+var postcss = require('gulp-postcss');
+var autoprefixer = require('autoprefixer');
+var mqpacker = require('css-mqpacker');
+var csswring = require('csswring');
var TEMPLATE_FOOTER = `}]);
angular.module('xos.ceilometerDashboard').run(function($location){$location.path('/')});
@@ -37,6 +41,28 @@
);
});
+ // minify css
+ gulp.task('css', function () {
+ var processors = [
+ autoprefixer({browsers: ['last 1 version']}),
+ mqpacker,
+ csswring
+ ];
+
+ gulp.src([
+ `${options.css}**/*.css`,
+ `!${options.css}dev.css`
+ ])
+ .pipe(postcss(processors))
+ .pipe(gulp.dest(options.tmp + '/css/'));
+ });
+
+ gulp.task('copyCss', ['css'], function(){
+ return gulp.src([`${options.tmp}/css/*.css`])
+ .pipe(concat('xosCeilometerDashboard.css'))
+ .pipe(gulp.dest(options.static + 'css/'))
+ });
+
// compile and minify scripts
gulp.task('scripts', function() {
return gulp.src([
@@ -67,12 +93,15 @@
.pipe(replace(/<!-- bower:css -->(\n.*)*\n<!-- endbower --><!-- endcss -->/, ''))
.pipe(replace(/<!-- bower:js -->(\n.*)*\n<!-- endbower --><!-- endjs -->/, ''))
.pipe(replace(/ng-app=".*"\s/, ''))
+ //rewriting css path
+ // .pipe(replace(/(<link.*">)/, ''))
// injecting minified files
.pipe(
inject(
gulp.src([
options.static + 'js/vendor/xosCeilometerDashboardVendor.js',
- options.static + 'js/xosCeilometerDashboard.js'
+ options.static + 'js/xosCeilometerDashboard.js',
+ options.static + 'css/xosCeilometerDashboard.css'
])
)
)
@@ -107,11 +136,13 @@
gulp.task('build', function() {
runSequence(
+ 'lint',
'templates',
'babel',
'scripts',
'wiredep',
'copyHtml',
+ 'copyCss',
'cleanTmp'
);
});
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js
index a4561b8..7268b13 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js
@@ -9,6 +9,7 @@
var wiredep = require('wiredep').stream;
var httpProxy = require('http-proxy');
var del = require('del');
+var debug = require('gulp-debug');
const environment = process.env.NODE_ENV;
@@ -86,28 +87,36 @@
// transpile js with sourceMaps
gulp.task('babel', function(){
- return gulp.src(options.scripts + '**/*.js')
+ return gulp.src([options.scripts + '**/*.js'])
.pipe(babel({sourceMaps: true}))
.pipe(gulp.dest(options.tmp));
});
// inject scripts
- gulp.task('injectScript', ['cleanTmp', 'babel'], function(){
- return gulp.src(options.src + 'index.html')
- .pipe(
- inject(
- gulp.src([
- options.tmp + '**/*.js',
- options.api + '*.js',
- options.helpers + '**/*.js'
- ])
- .pipe(angularFilesort()),
- {
- ignorePath: [options.src, '/../../ngXosLib']
- }
- )
- )
- .pipe(gulp.dest(options.src));
+ gulp.task('injectScript', function(){
+ console.log(options.tmp);
+ runSequence(
+ 'cleanTmp',
+ 'babel',
+ function() {
+ return gulp.src(options.src + 'index.html')
+ .pipe(
+ inject(
+ gulp.src([
+ options.tmp + '**/*.js',
+ options.api + '*.js',
+ options.helpers + '**/*.js'
+ ])
+ // .pipe(debug({title: 'unicorn:'}))
+ .pipe(angularFilesort()),
+ {
+ ignorePath: [options.src, '/../../ngXosLib']
+ }
+ )
+ )
+ .pipe(gulp.dest(options.src));
+ }
+ );
});
// inject CSS
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js
index f114774..de911e9 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js
@@ -5,6 +5,7 @@
var options = {
src: 'src/',
+ css: 'src/css/',
scripts: 'src/js/',
tmp: 'src/.tmp',
dist: 'dist/',
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js
index dbd344a..12d0697 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js
@@ -10,9 +10,8 @@
var bowerComponents = wiredep( {devDependencies: true} )[ 'js' ].map(function( file ){
return path.relative(process.cwd(), file);
});
-
-module.exports = function(config) {
/*eslint-enable*/
+module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
@@ -45,10 +44,17 @@
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'src/js/**/*.js': ['babel'],
- 'spec/**/*.test.js': ['babel'],
+ 'spec/**/*.js': ['babel'],
'src/**/*.html': ['ng-html2js']
},
+ babelPreprocessor: {
+ options: {
+ presets: ['es2015'],
+ sourceMap: 'inline'
+ }
+ },
+
ngHtml2JsPreprocessor: {
stripPrefix: 'src/', //strip the src path from template url (http://stackoverflow.com/questions/22869668/karma-unexpected-request-when-testing-angular-directive-even-with-ng-html2js)
moduleName: 'templates' // define the template module name
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json b/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json
index 661b343..0a9ccae 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json
@@ -7,6 +7,7 @@
"start": "gulp serve",
"prebuild": "npm install && bower install",
"build": "gulp",
+ "pretest": "npm install",
"test": "karma start",
"lint": "eslint src/js/"
},
@@ -19,7 +20,12 @@
"license": "MIT",
"dependencies": {},
"devDependencies": {
+ "autoprefixer": "^6.1.2",
+ "babel": "^6.3.13",
+ "babel-preset-es2015": "^6.3.13",
"browser-sync": "^2.9.11",
+ "css-mqpacker": "^4.0.0",
+ "csswring": "^4.1.1",
"del": "^2.0.2",
"eslint": "^1.8.0",
"eslint-plugin-angular": "linkmesrl/eslint-plugin-angular",
@@ -28,16 +34,26 @@
"gulp-angular-templatecache": "^1.8.0",
"gulp-babel": "^5.3.0",
"gulp-concat": "^2.6.0",
+ "gulp-debug": "^2.1.2",
"gulp-eslint": "^1.0.0",
"gulp-inject": "^3.0.0",
"gulp-minify-html": "^1.0.4",
"gulp-ng-annotate": "^1.1.0",
+ "gulp-postcss": "^6.0.1",
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.4",
"gulp-uglify": "^1.4.2",
"http-proxy": "^1.12.0",
+ "jasmine-core": "^2.4.1",
"karma": "^0.13.15",
+ "karma-babel-preprocessor": "^6.0.1",
+ "karma-jasmine": "^0.3.6",
+ "karma-mocha-reporter": "^1.1.3",
+ "karma-ng-html2js-preprocessor": "^0.2.0",
+ "karma-phantomjs-launcher": "^0.2.1",
"lodash": "^3.10.1",
+ "mocha": "^2.3.4",
+ "phantomjs": "^1.9.19",
"proxy-middleware": "^0.15.0",
"run-sequence": "^1.1.4",
"wiredep": "^3.0.0-beta",
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/.eslintrc b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/.eslintrc
new file mode 100644
index 0000000..ad4bc2d
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/.eslintrc
@@ -0,0 +1,9 @@
+{
+ "globals" :{
+ "describe": true,
+ "beforeEach": true,
+ "it": true,
+ "inject": true,
+ "expect": true
+ }
+}
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/backend.mock.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/backend.mock.js
new file mode 100644
index 0000000..c7642bb
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/backend.mock.js
@@ -0,0 +1,98 @@
+'use strict';
+(function () {
+
+ const meters = [
+ // service_1
+ // - slice_1
+ // - resource_1
+ // service_2
+ // - slice_2
+ // - resource_2
+ // - resource_3
+ // - slice_3
+ // - resource_4
+ {
+ service: 'service_1',
+ slice: 'slice_1',
+ resource_name: 'resource_1',
+ resource_id: 'resource_id_1',
+ name: 'instance_1',
+ unit: 'instance'
+ },
+ {
+ service: 'service_2',
+ slice: 'slice_2',
+ resource_name: 'resource_2',
+ resource_id: 'resource_id_2',
+ name: 'instance_2',
+ unit: 'instance'
+ },
+ {
+ service: 'service_2',
+ slice: 'slice_2',
+ resource_name: 'resource_3',
+ resource_id: 'resource_id_3',
+ name: 'instance_2',
+ unit: 'instance'
+ },
+ {
+ service: 'service_2',
+ slice: 'slice_3',
+ resource_name: 'resource_4',
+ resource_id: 'resource_id_4',
+ name: 'instance_3',
+ unit: 'instance'
+ }
+ ];
+
+ const samples = [
+ {
+ meter: 'cpu',
+ resource_name: 'fakeName',
+ project_id: 'fakeTenant',
+ timestamp: '2015-12-15T00:34:08',
+ volume: 110
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'fakeName',
+ project_id: 'fakeTenant',
+ timestamp: '2015-12-15T00:44:08',
+ volume: 120
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'anotherName',
+ project_id: 'anotherTenant',
+ timestamp: '2015-12-15T00:24:08',
+ volume: 210
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'anotherName',
+ project_id: 'anotherTenant',
+ timestamp: '2015-12-15T00:34:08',
+ volume: 220
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'anotherName',
+ project_id: 'anotherTenant',
+ timestamp: '2015-12-15T00:44:08',
+ volume: 230
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'thirdName',
+ project_id: 'thirdTenant',
+ timestamp: '2015-12-15T00:44:08',
+ volume: 310
+ }
+ ];
+
+ angular.module('xos.ceilometerDashboard')
+ .run(($httpBackend) => {
+ $httpBackend.whenGET(/metersamples/).respond(samples);
+ $httpBackend.whenGET(/meters/).respond(meters);
+ });
+})();
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/ceilometer.test.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/ceilometer.test.js
new file mode 100644
index 0000000..c5bb850
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/ceilometer.test.js
@@ -0,0 +1,137 @@
+'use strict';
+
+describe('In Ceilometer View', () => {
+
+ var scope, element, vm, httpBackend;
+
+ beforeEach(module('xos.ceilometerDashboard'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject(($httpBackend, $rootScope) => {
+ httpBackend = $httpBackend;
+ scope = $rootScope.$new();
+ }))
+
+ describe('The dashboard', () => {
+ beforeEach(inject(function($httpBackend, $compile){
+ element = angular.element('<ceilometer-dashboard></ceilometer-dashboard>');
+ $compile(element)(scope);
+ scope.$digest();
+ vm = element.isolateScope().vm;
+ httpBackend.flush();
+ }));
+
+ describe('when loading meters', () => {
+ it('should group meters by services', () => {
+ expect(Object.keys(vm.projects).length).toBe(2);
+ });
+
+ it('should group services by slices', () => {
+ expect(Object.keys(vm.projects.service_2).length).toBe(2);
+ });
+
+ it('should group slices by resources', () => {
+ expect(Object.keys(vm.projects.service_2.slice_2).length).toBe(2);
+ });
+ });
+ });
+
+ describe('the sample view', () => {
+ beforeEach(inject(function($httpBackend, $compile, $stateParams){
+
+ $stateParams.name = 'fakeName';
+ $stateParams.tenant = 'fakeTenant';
+
+ element = angular.element('<ceilometer-samples></ceilometer-samples>');
+ $compile(element)(scope);
+ scope.$digest();
+ vm = element.isolateScope().vm;
+ httpBackend.flush();
+ }));
+
+ it('should group samples by resource_id', () => {
+ expect(Object.keys(vm.samplesList.fakeTenant).length).toBe(2)
+ expect(Object.keys(vm.samplesList.anotherTenant).length).toBe(3)
+ expect(Object.keys(vm.samplesList.thirdTenant).length).toBe(1)
+ });
+
+ it('should add the comparable samples to the dropdown list', () => {
+ expect(vm.sampleLabels[0].id).toEqual('anotherTenant')
+ expect(vm.sampleLabels[1].id).toEqual('thirdTenant')
+ });
+
+ it('should add the selected meter to the chart', () => {
+ expect(vm.chart.labels.length).toBe(2);
+ expect(vm.chart.series[0]).toBe('fakeTenant');
+ expect(vm.chart.data[0].length).toBe(2);
+ expect(vm.chart.data[0][0]).toBe(110);
+ expect(vm.chart.data[0][1]).toBe(120);
+ expect(vm.chartMeters[0].project_id).toBe('fakeTenant')
+ expect(vm.chartMeters[0].resource_name).toBe('fakeName')
+ });
+
+ it('should add a sample to the chart', () => {
+ vm.addMeterToChart('anotherTenant');
+ expect(vm.chart.labels.length).toBe(3);
+ expect(vm.chart.data[1].length).toBe(3);
+ expect(vm.chart.data[1][0]).toBe(210);
+ expect(vm.chart.data[1][1]).toBe(220);
+ expect(vm.chart.data[1][2]).toBe(230);
+ expect(vm.chartMeters[1].project_id).toBe('anotherTenant')
+ expect(vm.chartMeters[1].resource_name).toBe('anotherName')
+ });
+
+ it('should remove a sample from the chart', () => {
+ // for simplyvity add a tenant (it's tested)
+ vm.addMeterToChart('anotherTenant');
+ vm.removeFromChart(vm.chartMeters[0]);
+ expect(vm.chart.data[0].length).toBe(3);
+ expect(vm.chart.data[0][0]).toBe(210);
+ expect(vm.chart.data[0][1]).toBe(220);
+ expect(vm.chart.data[0][2]).toBe(230);
+ expect(vm.chartMeters[0].project_id).toBe('anotherTenant')
+ expect(vm.chartMeters[0].resource_name).toBe('anotherName')
+ });
+
+ describe('The format sample labels method', () => {
+ it('should create an array of unique labels', () => {
+ // unique because every resource has multiple samples (time-series)
+ const samples = [
+ {project_id: 1, resource_name: 'fakeName'},
+ {project_id: 1, resource_name: 'fakeName'},
+ {project_id: 2, resource_name: 'anotherName'},
+ {project_id: 2, resource_name: 'anotherName'}
+ ];
+
+ const result = vm.formatSamplesLabels(samples);
+
+ expect(result.length).toBe(2);
+ expect(result[0]).toEqual({id: 1, name: 'fakeName'});
+ expect(result[1]).toEqual({id: 2, name: 'anotherName'});
+ });
+ });
+ });
+});
+
+describe('The orderObjectByKey filter', () => {
+ var $filter;
+
+ beforeEach(function () {
+ module('xos.ceilometerDashboard');
+
+ inject(function (_$filter_) {
+ $filter = _$filter_;
+ });
+ });
+
+ it('should order an object by the key value', function () {
+ // Arrange.
+ const list = {c: 3, b: 2, a: 1};
+
+ // call the filter function
+ const result = $filter('orderObjectByKey')(list);
+
+ // Assert.
+ expect(result).toEqual({a: 1, b: 2, c: 3});
+ });
+});
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/sample.test.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/sample.test.js
deleted file mode 100644
index a224095..0000000
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/sample.test.js
+++ /dev/null
@@ -1,34 +0,0 @@
-'use strict';
-
-describe('The User List', () => {
-
- var scope, element, isolatedScope, httpBackend;
-
- beforeEach(module('xos.ceilometerDashboard'));
- beforeEach(module('templates'));
-
- beforeEach(inject(function($httpBackend, $compile, $rootScope){
-
- httpBackend = $httpBackend;
- // Setting up mock request
- $httpBackend.expectGET(/meters/).respond([
- {
- email: 'teo@onlab.us',
- firstname: 'Matteo',
- lastname: 'Scandolo'
- }
- ]);
-
- scope = $rootScope.$new();
- element = angular.element('<ceilometer-dashboard></ceilometer-dashboard>');
- $compile(element)(scope);
- scope.$digest();
- isolatedScope = element.isolateScope().vm;
- }));
-
- it('should load 1 users', () => {
- httpBackend.flush();
- expect(isolatedScope.meters.length).toBe(1);
- });
-
-});
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css
index e6fb7a8..879d7b4 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css
@@ -1,216 +1,263 @@
-/*ceilometer-dashboard{*/
+#xosCeilometerDashboard{
+ position: relative;
+}
- /* Panel Layout */
- .panel {
- margin-top: 10px;
+/* Panel Layout */
+.panel {
+ margin-top: 10px;
+}
+
+.panel-body:not(:first-child) {
+ border-top: 1px solid #e3e3e3;
+}
+
+.panel-body .row {
+ margin-top: 10px;
+}
+
+/* Chart details */
+.chart {
+ width: 100%;
+ height: 300px;
+}
+
+.btn-chart, .btn-chart:hover {
+ color: #fff;
+}
+
+.side-container {
+ position: relative;
+}
+
+.service-list {
+ margin-top: -10px;
+}
+
+.service-list h3 {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.service-list a {
+ text-decoration: none;
+ color: #333;
+}
+
+.meters, .stats {
+ margin-top: 25px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+}
+
+/* LOADER */
+.loader {
+ font-size: 10px;
+ margin: 150px auto;
+ text-indent: -9999em;
+ width: 11em;
+ height: 11em;
+ border-radius: 50%;
+ background: #ffffff;
+ background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ position: relative;
+ -webkit-animation: load3 1.4s infinite linear;
+ animation: load3 1.4s infinite linear;
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.loader:before {
+ width: 50%;
+ height: 50%;
+ background: #105E9E;
+ border-radius: 100% 0 0 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ content: '';
+}
+.loader:after {
+ background: #fff;
+ width: 75%;
+ height: 75%;
+ border-radius: 50%;
+ content: '';
+ margin: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+}
+@-webkit-keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+/* VIEW ANIMATION */
+
+[ui-view] {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+}
+
+/* FROM DASHBOARD TO DETAIL */
+
+/* dash out */
+[ui-view].ceilometerDashboard.ng-leave {
+ animation:1s bounceOutLeft ease;
+}
+/* samples in */
+[ui-view].samples.ng-enter {
+ animation:1s bounceInRight ease;
+}
+
+/* FROM DETAIL TO DASHBOARD */
+
+/* samples out */
+[ui-view].samples.ng-leave {
+ animation:1s bounceOutRight ease;
+}
+/* dash in */
+[ui-view].ceilometerDashboard.ng-enter {
+ animation:1s bounceInLeft ease;
+}
+
+/* COLUMS ANIMATION */
+/* when showing the thing */
+.animate .animate-slide-left.ng-hide-remove {
+ animation:0.5s bounceInRight ease;
+}
+
+/* when hiding the picture */
+.animate .animate-slide-left.ng-hide-add {
+ animation:0.5s bounceOutRight ease;
+}
+
+/* ANIMATIONS */
+
+@keyframes bounceInRight {
+ from, 60%, 75%, 90%, to {
+ animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
- .panel-body:not(:first-child) {
- border-top: 1px solid #e3e3e3;
+ from {
+ opacity: 0;
+ transform: translate3d(3000px, 0, 0);
}
- .panel-body .row {
- margin-top: 10px;
+ 60% {
+ opacity: 1;
+ transform: translate3d(-25px, 0, 0);
}
- /* Chart details */
- .chart {
- width: 100%;
- height: 300px;
+ 75% {
+ transform: translate3d(10px, 0, 0);
}
- .btn-chart, .btn-chart:hover {
- color: #fff;
+ 90% {
+ transform: translate3d(-5px, 0, 0);
}
- /* LOADER */
- .loader {
- font-size: 10px;
- margin: 150px auto;
- text-indent: -9999em;
- width: 11em;
- height: 11em;
- border-radius: 50%;
- background: #ffffff;
- background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- position: relative;
- -webkit-animation: load3 1.4s infinite linear;
- animation: load3 1.4s infinite linear;
- -webkit-transform: translateZ(0);
- -ms-transform: translateZ(0);
- transform: translateZ(0);
+ to {
+ transform: none;
}
- .loader:before {
- width: 50%;
- height: 50%;
- background: #105E9E;
- border-radius: 100% 0 0 0;
- position: absolute;
- top: 0;
- left: 0;
- content: '';
- }
- .loader:after {
- background: #fff;
- width: 75%;
- height: 75%;
- border-radius: 50%;
- content: '';
- margin: auto;
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- }
- @-webkit-keyframes load3 {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- 100% {
- -webkit-transform: rotate(360deg);
- transform: rotate(360deg);
- }
- }
- @keyframes load3 {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- 100% {
- -webkit-transform: rotate(360deg);
- transform: rotate(360deg);
- }
+}
+
+@keyframes bounceInLeft {
+ from, 60%, 75%, 90%, to {
+ animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
- /* VIEW ANIMATION */
-
- [ui-view] {
- position: absolute;
- top: 0;
- bottom: 0;
- width: 100%;
+ 0% {
+ opacity: 0;
+ transform: translate3d(-3000px, 0, 0);
}
- /* FROM DASHBOARD TO DETAIL */
-
- /* dash out */
- [ui-view].ceilometerDashboard.ng-leave {
- animation:1s bounceOutLeft ease;
- }
- /* samples in */
- [ui-view].samples.ng-enter {
- animation:1s bounceInRight ease;
+ 60% {
+ opacity: 1;
+ transform: translate3d(25px, 0, 0);
}
- /* FROM DETAIL TO DASHBOARD */
-
- /* samples out */
- [ui-view].samples.ng-leave {
- animation:1s bounceOutRight ease;
- }
- /* dash in */
- [ui-view].ceilometerDashboard.ng-enter {
- animation:1s bounceInLeft ease;
+ 75% {
+ transform: translate3d(-10px, 0, 0);
}
- /* COLUMS ANIMATION */
-
- /* when showing the thing */
- .animate .animate-slide-left.ng-hide-remove {
- animation:0.5s bounceInRight ease;
+ 90% {
+ transform: translate3d(5px, 0, 0);
}
- /* when hiding the picture */
- .animate .animate-slide-left.ng-hide-add {
- animation:0.5s bounceOutRight ease;
+ to {
+ transform: none;
}
-
- /* ANIMATIONS */
+}
- @keyframes bounceInRight {
- from, 60%, 75%, 90%, to {
- animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
- }
-
- from {
- opacity: 0;
- transform: translate3d(3000px, 0, 0);
- }
-
- 60% {
- opacity: 1;
- transform: translate3d(-25px, 0, 0);
- }
-
- 75% {
- transform: translate3d(10px, 0, 0);
- }
-
- 90% {
- transform: translate3d(-5px, 0, 0);
- }
-
- to {
- transform: none;
- }
+@keyframes slideInUp {
+ from {
+ transform: translate3d(0, 100%, 0);
+ visibility: visible;
}
- @keyframes bounceInLeft {
- from, 60%, 75%, 90%, to {
- animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
- }
+ to {
+ transform: translate3d(0, 0, 0);
+ }
+}
- 0% {
- opacity: 0;
- transform: translate3d(-3000px, 0, 0);
- }
-
- 60% {
- opacity: 1;
- transform: translate3d(25px, 0, 0);
- }
-
- 75% {
- transform: translate3d(-10px, 0, 0);
- }
-
- 90% {
- transform: translate3d(5px, 0, 0);
- }
-
- to {
- transform: none;
- }
+@keyframes bounceOutRight {
+ 20% {
+ opacity: 1;
+ transform: translate3d(-20px, 0, 0);
}
- @keyframes bounceOutRight {
- 20% {
- opacity: 1;
- transform: translate3d(-20px, 0, 0);
- }
+ to {
+ opacity: 0;
+ transform: translate3d(2000px, 0, 0);
+ }
+}
- to {
- opacity: 0;
- transform: translate3d(2000px, 0, 0);
- }
+@keyframes bounceOutLeft {
+ 20% {
+ opacity: 1;
+ transform: translate3d(20px, 0, 0);
}
- @keyframes bounceOutLeft {
- 20% {
- opacity: 1;
- transform: translate3d(20px, 0, 0);
- }
+ to {
+ opacity: 0;
+ transform: translate3d(-2000px, 0, 0);
+ }
+}
- to {
- opacity: 0;
- transform: translate3d(-2000px, 0, 0);
- }
+@keyframes slideOutDown {
+ from {
+ transform: translate3d(0, 0, 0);
}
-/*}
\ No newline at end of file
+ to {
+ visibility: hidden;
+ transform: translate3d(0, 100%, 0);
+ }
+}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css
index b72bfdc..228d394 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css
@@ -9,6 +9,6 @@
@media (min-width: 768px) {
#xosCeilometerDashboard {
- margin: 10px:;
+ margin: 10px
}
}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/grips/vertical.png b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/grips/vertical.png
deleted file mode 100644
index 0ac8fa1..0000000
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/grips/vertical.png
+++ /dev/null
Binary files differ
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/index.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/index.html
index de89045..bcd71a4 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/index.html
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/index.html
@@ -19,6 +19,8 @@
<script src="vendor/Chart.js/Chart.js"></script>
<script src="vendor/angular-chart.js/dist/angular-chart.js"></script>
<script src="vendor/angular-animate/angular-animate.js"></script>
+<script src="vendor/ui.bootstrap/src/accordion/accordion.js"></script>
+<script src="vendor/ui.bootstrap/src/collapse/collapse.js"></script>
<script src="vendor/jquery/dist/jquery.js"></script>
<script src="vendor/angular-mocks/angular-mocks.js"></script>
<script src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
@@ -27,6 +29,7 @@
<script src="vendor/ng-lodash/build/ng-lodash.js"></script>
<script src="vendor/bootstrap-css/js/bootstrap.min.js"></script>
<!-- endbower --><!-- endjs -->
+
<!-- inject:js -->
<script src="/xosHelpers/src/xosHelpers.module.js"></script>
<script src="/xosHelpers/src/services/noHyperlinks.interceptor.js"></script>
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js
index 5085813..a20d563 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js
@@ -7,7 +7,8 @@
'ui.router',
'xos.helpers',
'ngAnimate',
- 'chart.js'
+ 'chart.js',
+ 'ui.bootstrap.accordion'
])
.config(($stateProvider, $urlRouterProvider) => {
$stateProvider
@@ -18,16 +19,6 @@
.state('samples', {
url: '/:name/:tenant/samples',
template: '<ceilometer-samples></ceilometer-samples>'
- })
- .state('split', {
- url: '/split',
- controller: () => {
- console.log('split', Split);
- Split(['#one', '#two', '#three'], {
-
- });
- },
- templateUrl: 'templates/split.html'
});
$urlRouterProvider.otherwise('/');
})
@@ -37,23 +28,16 @@
.run(function($rootScope){
$rootScope.stateName = 'ceilometerDashboard';
$rootScope.$on('$stateChangeStart', (event, toState) => {
- console.log(toState.name);
$rootScope.stateName = toState.name;
})
})
-.service('Ceilometer', function($http, $q){
-
- this.sliceDetails = {};
-
- this.formatSliceDetails = (meters) => {
-
- };
+.service('Ceilometer', function($http, $q, lodash){
this.getMeters = () => {
let deferred = $q.defer();
- // $http.get('/xoslib/meters/', {cache: true})
- $http.get('../meters_mock.json', {cache: true})
+ $http.get('/xoslib/meters/', {cache: true})
+ // $http.get('../meters_mock.json', {cache: true})
.then((res) => {
deferred.resolve(res.data)
})
@@ -77,6 +61,26 @@
return deferred.promise;
}
+
+ this.getStats = (sliceName) => {
+ let deferred = $q.defer();
+
+ $http.get('/xoslib/meterstatistics/', {cache: true})
+ // $http.get('../stats_mock.son', {cache: true})
+ .then((res) => {
+ deferred.resolve(lodash.filter(res.data, {slice: sliceName}))
+ })
+ .catch((e) => {
+ deferred.reject(e);
+ });
+
+ return deferred.promise;
+ };
+
+ // hold dashboard status (opened service, slice, resource)
+ this.selectedService = null;
+ this.selectedSlice = null;
+ this.selectedResource = null;
})
.directive('ceilometerDashboard', function(lodash){
return {
@@ -87,18 +91,52 @@
templateUrl: 'templates/ceilometer-dashboard.tpl.html',
controller: function(Ceilometer){
+ console.log(Ceilometer.selectedService, Ceilometer.selectedSlice, Ceilometer.selectedResource);
+
+ // this open the accordion
+ this.accordion = {
+ open: {}
+ }
+
+ /**
+ * Open the active panel base on the service stored values
+ */
+ this.openPanels = () => {
+ if(Ceilometer.selectedService){
+ this.accordion.open[Ceilometer.selectedService] = true;
+ if(Ceilometer.selectedSlice){
+ this.selectedSlice = Ceilometer.selectedSlice;
+ this.selectedResources = this.projects[Ceilometer.selectedService][Ceilometer.selectedSlice]
+ if(Ceilometer.selectedResource){
+ this.selectedResource = Ceilometer.selectedResource;
+ this.selectedMeters = this.selectedResources[Ceilometer.selectedResource];
+ }
+ }
+ }
+ }
+
this.loadMeters = () => {
this.loader = true;
+ // TODO rename projects in meters
Ceilometer.getMeters()
.then(meters => {
- this.projects = lodash.groupBy(meters, 'project_name');
+ //group project by service
+ this.projects = lodash.groupBy(meters, 'service');
lodash.forEach(Object.keys(this.projects), (project) => {
- this.projects[project] = lodash.groupBy(this.projects[project], 'resource_id');
+ // inside each service group by slice
+ this.projects[project] = lodash.groupBy(this.projects[project], 'slice');
+ lodash.forEach(Object.keys(this.projects[project]), (slice) => {
+ // inside each service => slice group by resource
+ this.projects[project][slice] = lodash.groupBy(this.projects[project][slice], 'resource_name');
+ });
});
+
+ // open selected panels
+ this.openPanels();
})
.catch(err => {
- this.err = err;
+ this.error = err.data.detail;
})
.finally(() => {
this.loader = false;
@@ -114,14 +152,20 @@
* @returns void
*/
this.selectedResources = null;
- this.selectResources = (resources, slice) => {
+ this.selectResources = (resources, slice, service) => {
//cleaning
this.selectedResources = null;
this.selectedResource = null;
this.selectedMeters = null;
+ // hold the resource list for the current slice
this.selectedResources = resources;
this.selectedSlice = slice;
+ this.selectedService = service;
+
+ // store the status
+ Ceilometer.selectedSlice = slice;
+ Ceilometer.selectedService = service;
}
/**
@@ -133,6 +177,8 @@
this.selectedMeters = null;
this.selectMeters = (meters, resource) => {
this.selectedMeters = meters;
+
+ Ceilometer.selectedResource = resource;
this.selectedResource = resource;
}
@@ -151,6 +197,8 @@
templateUrl: 'templates/ceilometer-samples.tpl.html',
controller: function(Ceilometer) {
+ // console.log(Ceilometer.selectResource);
+
this.chartColors = [
'#286090',
'#F7464A',
@@ -174,9 +222,11 @@
if($stateParams.name && $stateParams.tenant){
this.name = $stateParams.name;
this.tenant = $stateParams.tenant;
+ // TODO rename tenant in project_id
}
-
- // Mock
+ else{
+ throw new Error('Missing Name and Tenant Params!');
+ }
/**
* Goes trough the array and format date to be used as labels
@@ -213,21 +263,21 @@
* @param string resource_id
*/
this.chartMeters = [];
- this.addMeterToChart = (resource_id) => {
- this.chart['labels'] = this.getLabels(lodash.sortBy(this.samplesList[resource_id], 'timestamp'));
- this.chart['series'].push(resource_id);
- this.chart['data'].push(this.getData(lodash.sortBy(this.samplesList[resource_id], 'timestamp')));
- this.chartMeters.push(resource_id);
- lodash.remove(this.sampleLabels, {id: resource_id});
+ this.addMeterToChart = (project_id) => {
+ this.chart['labels'] = this.getLabels(lodash.sortBy(this.samplesList[project_id], 'timestamp'));
+ this.chart['series'].push(project_id);
+ this.chart['data'].push(this.getData(lodash.sortBy(this.samplesList[project_id], 'timestamp')));
+ this.chartMeters.push(this.samplesList[project_id][0]); //use the 0 as are all samples for the same resource and I need the name
+ lodash.remove(this.sampleLabels, {id: project_id});
}
- this.removeFromChart = (resource_id) => {
- this.chart.data.splice(this.chart.series.indexOf(resource_id), 1);
- this.chart.series.splice(this.chart.series.indexOf(resource_id), 1);
- this.chartMeters.splice(this.chartMeters.indexOf(resource_id), 1);
+ this.removeFromChart = (meter) => {
+ this.chart.data.splice(this.chart.series.indexOf(meter.project_id), 1);
+ this.chart.series.splice(this.chart.series.indexOf(meter.project_id), 1);
+ this.chartMeters.splice(lodash.findIndex(this.chartMeters, {project_id: meter.project_id}), 1);
this.sampleLabels.push({
- id: resource_id,
- // TODO add resource name
+ id: meter.project_id,
+ name: meter.resource_name || meter.project_id
})
};
@@ -237,13 +287,14 @@
this.formatSamplesLabels = (samples) => {
- return lodash.uniq(samples.reduce((labels, item) => {
+ return lodash.uniq(samples, 'project_id')
+ .reduce((labels, item) => {
labels.push({
- id: item.resource_id,
- // TODO add resource name
+ id: item.project_id,
+ name: item.resource_name || item.project_id
});
return labels;
- }, []), item => item.id);
+ }, []);
}
@@ -258,7 +309,7 @@
.then(res => {
// setup data for visualization
- this.samplesList = lodash.groupBy(res, 'resource_id');
+ this.samplesList = lodash.groupBy(res, 'project_id');
this.sampleLabels = this.formatSamplesLabels(res);
// add current meter to chart
@@ -266,7 +317,7 @@
})
.catch(err => {
- console.warn(err);
+ this.error = err.data.detail;
})
.finally(() => {
this.loader = false;
@@ -276,4 +327,49 @@
this.showSamples();
}
}
-});
\ No newline at end of file
+})
+.directive('ceilometerStats', function(){
+ return {
+ restrict: 'E',
+ scope: {
+ name: '=name',
+ },
+ bindToController: true,
+ controllerAs: 'vm',
+ templateUrl: 'templates/ceilometer-stats.tpl.html',
+ controller: function($scope, Ceilometer) {
+ this.getStats = () => {
+ this.loader = true;
+ Ceilometer.getStats(this.name)
+ .then(res => {
+ this.stats = res;
+ })
+ .catch(err => {
+ this.error = err.data;
+ })
+ .finally(() => {
+ this.loader = false;
+ });
+ };
+
+ this.getStats();
+
+ $scope.$watch(() => this.name, () => {this.getStats();});
+ }
+ }
+})
+.filter('orderObjectByKey', function(lodash) {
+ return function(items) {
+
+ if(!items){
+ return;
+ }
+
+ return lodash.reduce(Object.keys(items).reverse(), (list, key) => {
+ list[key] = items[key];
+ return list;
+ }, {});
+
+ };
+});
+;
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/meters_mock.json b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/meters_mock.json
index e6203ed..7ff0c68 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/meters_mock.json
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/meters_mock.json
@@ -1,145 +1,1266 @@
[
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "subnet",
- "resource_id": "6ebbcbdb-a172-41bf-8014-686c017c3d5a",
- "label": "",
- "source": "openstack",
- "meter_id": "NmViYmNiZGItYTE3Mi00MWJmLTgwMTQtNjg2YzAxN2MzZDVhK3N1Ym5ldA==\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
- "type": "gauge",
- "unit": "subnet",
- "description": "Existence of subnet"
- },
- {
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "network",
- "resource_id": "2ccafd0d-630f-45db-9b0e-b58a9d1de494",
- "label": "",
- "source": "openstack",
- "meter_id": "MmNjYWZkMGQtNjMwZi00NWRiLTliMGUtYjU4YTlkMWRlNDk0K25ldHdvcms=\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
- "type": "gauge",
- "unit": "network",
- "description": "Existence of network"
- },
- {
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
"name": "instance",
- "resource_id": "03663f84-adb2-40cf-ac22-b48dd18909da",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "197bc772-ff13-4b68-96e6-d4a4b1730fe7",
"label": "",
"source": "openstack",
- "meter_id": "MDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhK2luc3RhbmNl\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_onos_volt-4",
+ "meter_id": "MTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3K2luc3RhbmNl\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
"type": "gauge",
"unit": "instance",
"description": "Existence of instance"
},
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "network.incoming.bytes.rate",
- "resource_id": "instance-0000000c-03663f84-adb2-40cf-ac22-b48dd18909da-tapb62de4c8-a8",
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "instance",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "bde67a22-7579-4097-9406-c15eb2b9ae27",
"label": "",
"source": "openstack",
- "meter_id": "aW5zdGFuY2UtMDAwMDAwMGMtMDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhLXRh\ncGI2MmRlNGM4LWE4K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_onos_vbng-2",
+ "meter_id": "YmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3K2luc3RhbmNl\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
"type": "gauge",
- "unit": "B/s",
- "description": "Average rate per sec of incoming bytes on a VM network interface"
+ "unit": "instance",
+ "description": "Existence of instance"
},
{
- "project_name": "mysite_vcpe",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "port",
- "resource_id": "a14625cf-4184-460c-bef2-a2f8ff2054de",
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "instance",
+ "service": "Other",
+ "resource_id": "0a802169-5918-4c28-9014-635ae6602cdb",
"label": "",
"source": "openstack",
- "meter_id": "YTE0NjI1Y2YtNDE4NC00NjBjLWJlZjItYTJmOGZmMjA1NGRlK3BvcnQ=\n",
- "project_id": "1e948b44facc4efd81567d94b7c4d7a8",
+ "resource_name": "mysite_volt-5",
+ "meter_id": "MGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiK2luc3RhbmNl\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
"type": "gauge",
- "unit": "port",
- "description": "Existence of port"
+ "unit": "instance",
+ "description": "Existence of instance"
},
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "cpu_util",
- "resource_id": "03663f84-adb2-40cf-ac22-b48dd18909da",
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "instance",
+ "service": "service_vcpe",
+ "resource_id": "f71e7c55-2435-45a4-aa9a-073f97ceccbc",
"label": "",
"source": "openstack",
- "meter_id": "MDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhK2NwdV91dGls\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_vcpe-7",
+ "meter_id": "ZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjK2luc3RhbmNl\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
"type": "gauge",
- "unit": "%",
- "description": "Average CPU utilization"
+ "unit": "instance",
+ "description": "Existence of instance"
},
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "vcpus",
- "resource_id": "03663f84-adb2-40cf-ac22-b48dd18909da",
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "instance",
+ "service": "Other",
+ "resource_id": "98535996-e184-4996-a28e-61647e5d31d0",
"label": "",
"source": "openstack",
- "meter_id": "MDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhK3ZjcHVz\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_vbng-6",
+ "meter_id": "OTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwK2luc3RhbmNl\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
"type": "gauge",
- "unit": "vcpu",
- "description": "Number of VCPUs"
+ "unit": "instance",
+ "description": "Existence of instance"
},
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "network.outgoing.bytes.rate",
- "resource_id": "instance-0000000c-03663f84-adb2-40cf-ac22-b48dd18909da-tapb62de4c8-a8",
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "instance",
+ "service": "Other",
+ "resource_id": "f5c71396-9092-42da-91ec-434259bde2ef",
"label": "",
"source": "openstack",
- "meter_id": "aW5zdGFuY2UtMDAwMDAwMGMtMDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhLXRh\ncGI2MmRlNGM4LWE4K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_clients-3",
+ "meter_id": "ZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmK2luc3RhbmNl\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
"type": "gauge",
- "unit": "B/s",
- "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ "unit": "instance",
+ "description": "Existence of instance"
},
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "instance",
+ "service": "service_ceilometer",
+ "resource_id": "bdb0ff14-e848-446c-acb4-63e232487dc0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_ceilometer-8",
+ "meter_id": "YmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwK2luc3RhbmNl\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
"name": "memory",
- "resource_id": "03663f84-adb2-40cf-ac22-b48dd18909da",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "197bc772-ff13-4b68-96e6-d4a4b1730fe7",
"label": "",
"source": "openstack",
- "meter_id": "MDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhK21lbW9yeQ==\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_onos_volt-4",
+ "meter_id": "MTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3K21lbW9yeQ==\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
"type": "gauge",
"unit": "MB",
"description": "Volume of RAM"
},
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "cpu",
- "resource_id": "03663f84-adb2-40cf-ac22-b48dd18909da",
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "bde67a22-7579-4097-9406-c15eb2b9ae27",
"label": "",
"source": "openstack",
- "meter_id": "MDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhK2NwdQ==\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_onos_vbng-2",
+ "meter_id": "YmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3K21lbW9yeQ==\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory",
+ "service": "Other",
+ "resource_id": "0a802169-5918-4c28-9014-635ae6602cdb",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_volt-5",
+ "meter_id": "MGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiK21lbW9yeQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory",
+ "service": "service_vcpe",
+ "resource_id": "f71e7c55-2435-45a4-aa9a-073f97ceccbc",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vcpe-7",
+ "meter_id": "ZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjK21lbW9yeQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory",
+ "service": "Other",
+ "resource_id": "98535996-e184-4996-a28e-61647e5d31d0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vbng-6",
+ "meter_id": "OTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwK21lbW9yeQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory",
+ "service": "Other",
+ "resource_id": "f5c71396-9092-42da-91ec-434259bde2ef",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_clients-3",
+ "meter_id": "ZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmK21lbW9yeQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory",
+ "service": "service_ceilometer",
+ "resource_id": "bdb0ff14-e848-446c-acb4-63e232487dc0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_ceilometer-8",
+ "meter_id": "YmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwK21lbW9yeQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory.usage",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "197bc772-ff13-4b68-96e6-d4a4b1730fe7",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_onos_volt-4",
+ "meter_id": "MTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3K21lbW9yeS51c2FnZQ==\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory.usage",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "bde67a22-7579-4097-9406-c15eb2b9ae27",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_onos_vbng-2",
+ "meter_id": "YmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3K21lbW9yeS51c2FnZQ==\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory.usage",
+ "service": "Other",
+ "resource_id": "0a802169-5918-4c28-9014-635ae6602cdb",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_volt-5",
+ "meter_id": "MGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiK21lbW9yeS51c2FnZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory.usage",
+ "service": "service_vcpe",
+ "resource_id": "f71e7c55-2435-45a4-aa9a-073f97ceccbc",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vcpe-7",
+ "meter_id": "ZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjK21lbW9yeS51c2FnZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory.usage",
+ "service": "Other",
+ "resource_id": "98535996-e184-4996-a28e-61647e5d31d0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vbng-6",
+ "meter_id": "OTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwK21lbW9yeS51c2FnZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory.usage",
+ "service": "Other",
+ "resource_id": "f5c71396-9092-42da-91ec-434259bde2ef",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_clients-3",
+ "meter_id": "ZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmK21lbW9yeS51c2FnZQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "memory.usage",
+ "service": "service_ceilometer",
+ "resource_id": "bdb0ff14-e848-446c-acb4-63e232487dc0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_ceilometer-8",
+ "meter_id": "YmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwK21lbW9yeS51c2FnZQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "MB",
+ "description": "Volume of RAM used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "197bc772-ff13-4b68-96e6-d4a4b1730fe7",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_onos_volt-4",
+ "meter_id": "MTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3K2NwdQ==\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
"type": "cumulative",
"unit": "ns",
"description": "CPU time used"
},
{
- "project_name": "mysite_onos_vbng",
- "user_id": "bcb8c1f07ab94a948b0ea491f2ba43f1",
- "name": "memory.usage",
- "resource_id": "03663f84-adb2-40cf-ac22-b48dd18909da",
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "bde67a22-7579-4097-9406-c15eb2b9ae27",
"label": "",
"source": "openstack",
- "meter_id": "MDM2NjNmODQtYWRiMi00MGNmLWFjMjItYjQ4ZGQxODkwOWRhK21lbW9yeS51c2FnZQ==\n",
- "project_id": "75bf7d7deee744749ac76dc6d2e22c28",
+ "resource_name": "mysite_onos_vbng-2",
+ "meter_id": "YmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3K2NwdQ==\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "cumulative",
+ "unit": "ns",
+ "description": "CPU time used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu",
+ "service": "Other",
+ "resource_id": "0a802169-5918-4c28-9014-635ae6602cdb",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_volt-5",
+ "meter_id": "MGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiK2NwdQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "cumulative",
+ "unit": "ns",
+ "description": "CPU time used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu",
+ "service": "service_vcpe",
+ "resource_id": "f71e7c55-2435-45a4-aa9a-073f97ceccbc",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vcpe-7",
+ "meter_id": "ZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjK2NwdQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "cumulative",
+ "unit": "ns",
+ "description": "CPU time used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu",
+ "service": "Other",
+ "resource_id": "98535996-e184-4996-a28e-61647e5d31d0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vbng-6",
+ "meter_id": "OTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwK2NwdQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "cumulative",
+ "unit": "ns",
+ "description": "CPU time used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu",
+ "service": "Other",
+ "resource_id": "f5c71396-9092-42da-91ec-434259bde2ef",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_clients-3",
+ "meter_id": "ZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmK2NwdQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "cumulative",
+ "unit": "ns",
+ "description": "CPU time used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu",
+ "service": "service_ceilometer",
+ "resource_id": "bdb0ff14-e848-446c-acb4-63e232487dc0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_ceilometer-8",
+ "meter_id": "YmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwK2NwdQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "cumulative",
+ "unit": "ns",
+ "description": "CPU time used"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu_util",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "197bc772-ff13-4b68-96e6-d4a4b1730fe7",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_onos_volt-4",
+ "meter_id": "MTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3K2NwdV91dGls\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
"type": "gauge",
- "unit": "MB",
- "description": "Volume of RAM used"
+ "unit": "%",
+ "description": "Average CPU utilization"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu_util",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "bde67a22-7579-4097-9406-c15eb2b9ae27",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_onos_vbng-2",
+ "meter_id": "YmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3K2NwdV91dGls\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "gauge",
+ "unit": "%",
+ "description": "Average CPU utilization"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu_util",
+ "service": "Other",
+ "resource_id": "0a802169-5918-4c28-9014-635ae6602cdb",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_volt-5",
+ "meter_id": "MGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiK2NwdV91dGls\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "%",
+ "description": "Average CPU utilization"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu_util",
+ "service": "service_vcpe",
+ "resource_id": "f71e7c55-2435-45a4-aa9a-073f97ceccbc",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vcpe-7",
+ "meter_id": "ZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjK2NwdV91dGls\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "%",
+ "description": "Average CPU utilization"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu_util",
+ "service": "Other",
+ "resource_id": "98535996-e184-4996-a28e-61647e5d31d0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_vbng-6",
+ "meter_id": "OTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwK2NwdV91dGls\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "%",
+ "description": "Average CPU utilization"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu_util",
+ "service": "Other",
+ "resource_id": "f5c71396-9092-42da-91ec-434259bde2ef",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_clients-3",
+ "meter_id": "ZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmK2NwdV91dGls\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "%",
+ "description": "Average CPU utilization"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "cpu_util",
+ "service": "service_ceilometer",
+ "resource_id": "bdb0ff14-e848-446c-acb4-63e232487dc0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "mysite_ceilometer-8",
+ "meter_id": "YmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwK2NwdV91dGls\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "%",
+ "description": "Average CPU utilization"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000002-197bc772-ff13-4b68-96e6-d4a4b1730fe7-tap27815de2-07",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap27815de2-07",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDItMTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3LXRh\ncDI3ODE1ZGUyLTA3K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000002-197bc772-ff13-4b68-96e6-d4a4b1730fe7-tap8f02bde6-e4",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap8f02bde6-e4",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDItMTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3LXRh\ncDhmMDJiZGU2LWU0K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000004-bde67a22-7579-4097-9406-c15eb2b9ae27-tap265bab7b-93",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap265bab7b-93",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDQtYmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3LXRh\ncDI2NWJhYjdiLTkzK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000004-bde67a22-7579-4097-9406-c15eb2b9ae27-tap6d838c10-05",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap6d838c10-05",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDQtYmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3LXRh\ncDZkODM4YzEwLTA1K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tap5ef062b7-1d",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap5ef062b7-1d",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncDVlZjA2MmI3LTFkK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tap905990b8-db",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap905990b8-db",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncDkwNTk5MGI4LWRiK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tapa216d1f0-3e",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapa216d1f0-3e",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncGEyMTZkMWYwLTNlK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tapd80be99a-b6",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapd80be99a-b6",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncGQ4MGJlOTlhLWI2K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tap5afd137f-19",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap5afd137f-19",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncDVhZmQxMzdmLTE5K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tap9a6306b4-7e",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap9a6306b4-7e",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncDlhNjMwNmI0LTdlK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tapc59abc32-a4",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapc59abc32-a4",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncGM1OWFiYzMyLWE0K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tapf1e00a14-22",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapf1e00a14-22",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncGYxZTAwYTE0LTIyK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tapabf29bde-bc",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapabf29bde-bc",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGFiZjI5YmRlLWJjK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tapbc16b000-82",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapbc16b000-82",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGJjMTZiMDAwLTgyK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tape44bc1cc-46",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tape44bc1cc-46",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGU0NGJjMWNjLTQ2K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tape4f20024-47",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tape4f20024-47",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGU0ZjIwMDI0LTQ3K25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000003-f5c71396-9092-42da-91ec-434259bde2ef-tap3518d7f8-9f",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap3518d7f8-9f",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDMtZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmLXRh\ncDM1MThkN2Y4LTlmK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000003-f5c71396-9092-42da-91ec-434259bde2ef-tap7409a9c5-e0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap7409a9c5-e0",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDMtZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmLXRh\ncDc0MDlhOWM1LWUwK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000003-f5c71396-9092-42da-91ec-434259bde2ef-tapde69764f-3d",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapde69764f-3d",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDMtZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmLXRh\ncGRlNjk3NjRmLTNkK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_ceilometer",
+ "resource_id": "instance-00000005-bdb0ff14-e848-446c-acb4-63e232487dc0-tap8d13e0d5-d2",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap8d13e0d5-d2",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDUtYmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwLXRh\ncDhkMTNlMGQ1LWQyK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_ceilometer",
+ "resource_id": "instance-00000005-bdb0ff14-e848-446c-acb4-63e232487dc0-tapa5d252a8-ae",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapa5d252a8-ae",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDUtYmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwLXRh\ncGE1ZDI1MmE4LWFlK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.incoming.bytes.rate",
+ "service": "service_ceilometer",
+ "resource_id": "instance-00000005-bdb0ff14-e848-446c-acb4-63e232487dc0-tapb06a526b-03",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapb06a526b-03",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDUtYmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwLXRh\ncGIwNmE1MjZiLTAzK25ldHdvcmsuaW5jb21pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000002-197bc772-ff13-4b68-96e6-d4a4b1730fe7-tap27815de2-07",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap27815de2-07",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDItMTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3LXRh\ncDI3ODE1ZGUyLTA3K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000002-197bc772-ff13-4b68-96e6-d4a4b1730fe7-tap8f02bde6-e4",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap8f02bde6-e4",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDItMTk3YmM3NzItZmYxMy00YjY4LTk2ZTYtZDRhNGIxNzMwZmU3LXRh\ncDhmMDJiZGU2LWU0K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "bfef8341327245d682c7bada50aceecb",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000004-bde67a22-7579-4097-9406-c15eb2b9ae27-tap265bab7b-93",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap265bab7b-93",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDQtYmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3LXRh\ncDI2NWJhYjdiLTkzK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_onos_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000004-bde67a22-7579-4097-9406-c15eb2b9ae27-tap6d838c10-05",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap6d838c10-05",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDQtYmRlNjdhMjItNzU3OS00MDk3LTk0MDYtYzE1ZWIyYjlhZTI3LXRh\ncDZkODM4YzEwLTA1K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "7c918e6765c24ee281f3ee8692fd102c",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tap5ef062b7-1d",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap5ef062b7-1d",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncDVlZjA2MmI3LTFkK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tap905990b8-db",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap905990b8-db",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncDkwNTk5MGI4LWRiK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tapa216d1f0-3e",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapa216d1f0-3e",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncGEyMTZkMWYwLTNlK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_volt",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000001-0a802169-5918-4c28-9014-635ae6602cdb-tapd80be99a-b6",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapd80be99a-b6",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDEtMGE4MDIxNjktNTkxOC00YzI4LTkwMTQtNjM1YWU2NjAyY2RiLXRh\ncGQ4MGJlOTlhLWI2K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f506380a49a24389ae0d8469274e3279",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tap5afd137f-19",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap5afd137f-19",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncDVhZmQxMzdmLTE5K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tap9a6306b4-7e",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap9a6306b4-7e",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncDlhNjMwNmI0LTdlK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tapc59abc32-a4",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapc59abc32-a4",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncGM1OWFiYzMyLWE0K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vcpe",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_vcpe",
+ "resource_id": "instance-00000006-f71e7c55-2435-45a4-aa9a-073f97ceccbc-tapf1e00a14-22",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapf1e00a14-22",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDYtZjcxZTdjNTUtMjQzNS00NWE0LWFhOWEtMDczZjk3Y2VjY2JjLXRh\ncGYxZTAwYTE0LTIyK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "61a5d4b37b5d43718854916079760c0d",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tapabf29bde-bc",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapabf29bde-bc",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGFiZjI5YmRlLWJjK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tapbc16b000-82",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapbc16b000-82",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGJjMTZiMDAwLTgyK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tape44bc1cc-46",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tape44bc1cc-46",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGU0NGJjMWNjLTQ2K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_vbng",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000007-98535996-e184-4996-a28e-61647e5d31d0-tape4f20024-47",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tape4f20024-47",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDctOTg1MzU5OTYtZTE4NC00OTk2LWEyOGUtNjE2NDdlNWQzMWQwLXRh\ncGU0ZjIwMDI0LTQ3K25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "c92cf450df4640d6952c0276730e5048",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000003-f5c71396-9092-42da-91ec-434259bde2ef-tap3518d7f8-9f",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap3518d7f8-9f",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDMtZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmLXRh\ncDM1MThkN2Y4LTlmK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000003-f5c71396-9092-42da-91ec-434259bde2ef-tap7409a9c5-e0",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap7409a9c5-e0",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDMtZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmLXRh\ncDc0MDlhOWM1LWUwK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_clients",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "Other",
+ "resource_id": "instance-00000003-f5c71396-9092-42da-91ec-434259bde2ef-tapde69764f-3d",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapde69764f-3d",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDMtZjVjNzEzOTYtOTA5Mi00MmRhLTkxZWMtNDM0MjU5YmRlMmVmLXRh\ncGRlNjk3NjRmLTNkK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "f884c440474b40808a8adcdece5f45ef",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_ceilometer",
+ "resource_id": "instance-00000005-bdb0ff14-e848-446c-acb4-63e232487dc0-tap8d13e0d5-d2",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tap8d13e0d5-d2",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDUtYmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwLXRh\ncDhkMTNlMGQ1LWQyK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_ceilometer",
+ "resource_id": "instance-00000005-bdb0ff14-e848-446c-acb4-63e232487dc0-tapa5d252a8-ae",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapa5d252a8-ae",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDUtYmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwLXRh\ncGE1ZDI1MmE4LWFlK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "category": "Nova",
+ "slice": "mysite_ceilometer",
+ "user_id": "36e376b1072443758a0314f62fa8a414",
+ "name": "network.outgoing.bytes.rate",
+ "service": "service_ceilometer",
+ "resource_id": "instance-00000005-bdb0ff14-e848-446c-acb4-63e232487dc0-tapb06a526b-03",
+ "label": "",
+ "source": "openstack",
+ "resource_name": "tapb06a526b-03",
+ "meter_id": "aW5zdGFuY2UtMDAwMDAwMDUtYmRiMGZmMTQtZTg0OC00NDZjLWFjYjQtNjNlMjMyNDg3ZGMwLXRh\ncGIwNmE1MjZiLTAzK25ldHdvcmsub3V0Z29pbmcuYnl0ZXMucmF0ZQ==\n",
+ "project_id": "920d70bc63574552bbb3c3fb262ee1bc",
+ "type": "gauge",
+ "unit": "B/s",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
}
]
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/stats_mock.json b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/stats_mock.json
new file mode 100644
index 0000000..5dd083a
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/stats_mock.json
@@ -0,0 +1,950 @@
+[
+ {
+ "value": 1.0,
+ "unit": "instance",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "c7f44959-490b-4d24-8043-66a096c7cae0",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "value": 1.0,
+ "unit": "instance",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "afac5cb6-72c7-4c25-b281-7a442835b395",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "value": 1.0,
+ "unit": "instance",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "9ec8c981-feb8-46c1-a1f6-3438702ee170",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "value": 1.0,
+ "unit": "instance",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "274134cc-700a-4392-8226-447a2f35cc1e",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "value": 1.0,
+ "unit": "instance",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "e66d524e-9ce1-4ec2-81bb-c95043fb8e4f",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "value": 1.0,
+ "unit": "instance",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "a8214ed9-e222-484b-93c2-9245e4712a99",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "value": 1.0,
+ "unit": "instance",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "7d483484-a660-4307-b081-af1e4dd07eae",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "instance",
+ "description": "Existence of instance"
+ },
+ {
+ "value": 2048.0,
+ "unit": "MB",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "c7f44959-490b-4d24-8043-66a096c7cae0",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory",
+ "description": "Volume of RAM"
+ },
+ {
+ "value": 2048.0,
+ "unit": "MB",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "afac5cb6-72c7-4c25-b281-7a442835b395",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory",
+ "description": "Volume of RAM"
+ },
+ {
+ "value": 2048.0,
+ "unit": "MB",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "9ec8c981-feb8-46c1-a1f6-3438702ee170",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory",
+ "description": "Volume of RAM"
+ },
+ {
+ "value": 2048.0,
+ "unit": "MB",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "274134cc-700a-4392-8226-447a2f35cc1e",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory",
+ "description": "Volume of RAM"
+ },
+ {
+ "value": 2048.0,
+ "unit": "MB",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "e66d524e-9ce1-4ec2-81bb-c95043fb8e4f",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory",
+ "description": "Volume of RAM"
+ },
+ {
+ "value": 2048.0,
+ "unit": "MB",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "a8214ed9-e222-484b-93c2-9245e4712a99",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory",
+ "description": "Volume of RAM"
+ },
+ {
+ "value": 2048.0,
+ "unit": "MB",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "7d483484-a660-4307-b081-af1e4dd07eae",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory",
+ "description": "Volume of RAM"
+ },
+ {
+ "value": 1507.9379310344827,
+ "unit": "MB",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "c7f44959-490b-4d24-8043-66a096c7cae0",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory.usage",
+ "description": "Volume of RAM used"
+ },
+ {
+ "value": 374.6965517241379,
+ "unit": "MB",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "afac5cb6-72c7-4c25-b281-7a442835b395",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory.usage",
+ "description": "Volume of RAM used"
+ },
+ {
+ "value": 375.1655172413793,
+ "unit": "MB",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "9ec8c981-feb8-46c1-a1f6-3438702ee170",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory.usage",
+ "description": "Volume of RAM used"
+ },
+ {
+ "value": 1786.7310344827586,
+ "unit": "MB",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "274134cc-700a-4392-8226-447a2f35cc1e",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory.usage",
+ "description": "Volume of RAM used"
+ },
+ {
+ "value": 1797.2413793103449,
+ "unit": "MB",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "e66d524e-9ce1-4ec2-81bb-c95043fb8e4f",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory.usage",
+ "description": "Volume of RAM used"
+ },
+ {
+ "value": 376.36551724137934,
+ "unit": "MB",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "a8214ed9-e222-484b-93c2-9245e4712a99",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory.usage",
+ "description": "Volume of RAM used"
+ },
+ {
+ "value": 373.5448275862069,
+ "unit": "MB",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "7d483484-a660-4307-b081-af1e4dd07eae",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "memory.usage",
+ "description": "Volume of RAM used"
+ },
+ {
+ "value": 194620344827.5862,
+ "unit": "ns",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "c7f44959-490b-4d24-8043-66a096c7cae0",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu",
+ "description": "CPU time used"
+ },
+ {
+ "value": 93601310344.82759,
+ "unit": "ns",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "afac5cb6-72c7-4c25-b281-7a442835b395",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu",
+ "description": "CPU time used"
+ },
+ {
+ "value": 93402206896.55173,
+ "unit": "ns",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "9ec8c981-feb8-46c1-a1f6-3438702ee170",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu",
+ "description": "CPU time used"
+ },
+ {
+ "value": 4394690965517.241,
+ "unit": "ns",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "274134cc-700a-4392-8226-447a2f35cc1e",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu",
+ "description": "CPU time used"
+ },
+ {
+ "value": 4025309517241.3794,
+ "unit": "ns",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "e66d524e-9ce1-4ec2-81bb-c95043fb8e4f",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu",
+ "description": "CPU time used"
+ },
+ {
+ "value": 90704896551.72414,
+ "unit": "ns",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "a8214ed9-e222-484b-93c2-9245e4712a99",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu",
+ "description": "CPU time used"
+ },
+ {
+ "value": 93930827586.2069,
+ "unit": "ns",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "7d483484-a660-4307-b081-af1e4dd07eae",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu",
+ "description": "CPU time used"
+ },
+ {
+ "value": 0.2539938837459742,
+ "unit": "%",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "c7f44959-490b-4d24-8043-66a096c7cae0",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu_util",
+ "description": "Average CPU utilization"
+ },
+ {
+ "value": 0.1430115727449207,
+ "unit": "%",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "afac5cb6-72c7-4c25-b281-7a442835b395",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu_util",
+ "description": "Average CPU utilization"
+ },
+ {
+ "value": 0.14234621932639643,
+ "unit": "%",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "9ec8c981-feb8-46c1-a1f6-3438702ee170",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu_util",
+ "description": "Average CPU utilization"
+ },
+ {
+ "value": 9.501434897077173,
+ "unit": "%",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "274134cc-700a-4392-8226-447a2f35cc1e",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu_util",
+ "description": "Average CPU utilization"
+ },
+ {
+ "value": 8.59252727701459,
+ "unit": "%",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "e66d524e-9ce1-4ec2-81bb-c95043fb8e4f",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu_util",
+ "description": "Average CPU utilization"
+ },
+ {
+ "value": 0.13846207922030151,
+ "unit": "%",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "a8214ed9-e222-484b-93c2-9245e4712a99",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu_util",
+ "description": "Average CPU utilization"
+ },
+ {
+ "value": 0.14287395279840676,
+ "unit": "%",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "7d483484-a660-4307-b081-af1e4dd07eae",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "cpu_util",
+ "description": "Average CPU utilization"
+ },
+ {
+ "value": 88.53419771575258,
+ "unit": "B/s",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "instance-0000001b-c7f44959-490b-4d24-8043-66a096c7cae0-tapcadfbd73-5b",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.009455996028375395,
+ "unit": "B/s",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "instance-0000001b-c7f44959-490b-4d24-8043-66a096c7cae0-tap972eb016-96",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.009455996028375395,
+ "unit": "B/s",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "instance-0000001b-c7f44959-490b-4d24-8043-66a096c7cae0-tapf56382ad-45",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 124.74842906323501,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap79d13f74-62",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.017425896307365425,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap25ae020a-23",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.0174337765740103,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap8382609c-7c",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.009424851354967827,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap7bbe02e0-09",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 127.2159155680703,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tap308ba38c-64",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 1.996809016615307,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tap2aadc958-57",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.00944055944055944,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tap0b518c8d-01",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.017428347945877158,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tapaf0c7436-e8",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.009471769187962845,
+ "unit": "B/s",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000017-274134cc-700a-4392-8226-447a2f35cc1e-tap4b98f4d2-7e",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 33.618374055863,
+ "unit": "B/s",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000017-274134cc-700a-4392-8226-447a2f35cc1e-tap35a9b09a-29",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.009448122592881327,
+ "unit": "B/s",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000019-e66d524e-9ce1-4ec2-81bb-c95043fb8e4f-tap6717e37b-5a",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 33.6291738301644,
+ "unit": "B/s",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000019-e66d524e-9ce1-4ec2-81bb-c95043fb8e4f-tap35b38817-7f",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.009463869463869463,
+ "unit": "B/s",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-00000018-a8214ed9-e222-484b-93c2-9245e4712a99-tapaf9418d8-68",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.017437164857185466,
+ "unit": "B/s",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-00000018-a8214ed9-e222-484b-93c2-9245e4712a99-tap56d0c6f9-27",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 124.61289583768621,
+ "unit": "B/s",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-00000018-a8214ed9-e222-484b-93c2-9245e4712a99-tap31f27f17-47",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 123.65339047759299,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tap4894ed8a-51",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.009440585664408507,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tap31c8ec21-34",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.01743467844779237,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tap2605ab77-0a",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 0.013442333959863174,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tapeea51a4b-f3",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.incoming.bytes.rate",
+ "description": "Average rate per sec of incoming bytes on a VM network interface"
+ },
+ {
+ "value": 22.145300578664518,
+ "unit": "B/s",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "instance-0000001b-c7f44959-490b-4d24-8043-66a096c7cae0-tapcadfbd73-5b",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "instance-0000001b-c7f44959-490b-4d24-8043-66a096c7cae0-tap972eb016-96",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_ceilometer",
+ "name": "none",
+ "service": "service_ceilometer",
+ "resource_id": "instance-0000001b-c7f44959-490b-4d24-8043-66a096c7cae0-tapf56382ad-45",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 1.3187296037296037,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap79d13f74-62",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap25ae020a-23",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap8382609c-7c",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_vcpe",
+ "name": "none",
+ "service": "service_vcpe",
+ "resource_id": "instance-0000001a-afac5cb6-72c7-4c25-b281-7a442835b395-tap7bbe02e0-09",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 3.087960372960373,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tap308ba38c-64",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tap2aadc958-57",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tap0b518c8d-01",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_vbng",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001c-9ec8c981-feb8-46c1-a1f6-3438702ee170-tapaf0c7436-e8",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000017-274134cc-700a-4392-8226-447a2f35cc1e-tap4b98f4d2-7e",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.68399416060279,
+ "unit": "B/s",
+ "slice": "mysite_onos_volt",
+ "name": "none",
+ "service": "service_ONOS_vOLT",
+ "resource_id": "instance-00000017-274134cc-700a-4392-8226-447a2f35cc1e-tap35a9b09a-29",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000019-e66d524e-9ce1-4ec2-81bb-c95043fb8e4f-tap6717e37b-5a",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.5502331002331002,
+ "unit": "B/s",
+ "slice": "mysite_onos_vbng",
+ "name": "none",
+ "service": "service_ONOS_vBNG",
+ "resource_id": "instance-00000019-e66d524e-9ce1-4ec2-81bb-c95043fb8e4f-tap35b38817-7f",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-00000018-a8214ed9-e222-484b-93c2-9245e4712a99-tapaf9418d8-68",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-00000018-a8214ed9-e222-484b-93c2-9245e4712a99-tap56d0c6f9-27",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 1.2715034965034964,
+ "unit": "B/s",
+ "slice": "mysite_clients",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-00000018-a8214ed9-e222-484b-93c2-9245e4712a99-tap31f27f17-47",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.441946386946387,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tap4894ed8a-51",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tap31c8ec21-34",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tap2605ab77-0a",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ },
+ {
+ "value": 0.008951048951048951,
+ "unit": "B/s",
+ "slice": "mysite_volt",
+ "name": "none",
+ "service": "Other",
+ "resource_id": "instance-0000001d-7d483484-a660-4307-b081-af1e4dd07eae-tapeea51a4b-f3",
+ "time": "2015-12-10T00:44:10",
+ "type": "Nova",
+ "meter": "network.outgoing.bytes.rate",
+ "description": "Average rate per sec of outgoing bytes on a VM network interface"
+ }
+]
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/accordion-group.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/accordion-group.html
new file mode 100644
index 0000000..069141d
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/accordion-group.html
@@ -0,0 +1,10 @@
+<div class="panel {{panelClass || 'panel-default'}}">
+ <div class="panel-heading" ng-keypress="toggleOpen($event)">
+ <h3>
+ <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
+ </h3>
+ </div>
+ <div class="panel-collapse collapse" uib-collapse="!isOpen">
+ <div class="panel-body" ng-transclude></div>
+ </div>
+</div>
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/accordion.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/accordion.html
new file mode 100644
index 0000000..ba428f3
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/accordion.html
@@ -0,0 +1 @@
+<div class="panel-group" ng-transclude></div>
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html
index 2227659..f04a974 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html
@@ -1,7 +1,19 @@
<div class="row">
- <div class="col-sm-12">
+ <div class="col-sm-10">
<h1>XOS Monitoring Statistics</h1>
</div>
+ <div class="col-xs-2 text-right">
+ <a href="" class="btn btn-default"
+ ng-show="vm.selectedResources && !vm.showStats"
+ ng-click="vm.showStats = true">
+ <i class="glyphicon glyphicon-transfer"></i>
+ </a>
+ <a href="" class="btn btn-default"
+ ng-show="vm.selectedResources && vm.showStats"
+ ng-click="vm.showStats = false">
+ <i class="glyphicon glyphicon-transfer"></i>
+ </a>
+ </div>
</div>
<div class="row" ng-show="vm.loader">
@@ -12,56 +24,91 @@
<section ng-hide="vm.loader" ng-class="{animate: !vm.loader}">
<div class="row">
- <div class="col-sm-4">
- <div class="list-group">
- <div class="list-group-item">
- <h2>Service Name</h2>
- </div>
- <a href="#" ng-click="vm.selectResources(resources, slice)" class="list-group-item" ng-repeat="(slice, resources) in vm.projects" ng-class="{active: slice === vm.selectedSlice}">
- {{slice}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>
- </a>
- </div>
+ <div class="col-sm-3 service-list">
+ <h3>XOS Service: </h3>
+ <uib-accordion close-others="true" template-url="templates/accordion.html">
+ <uib-accordion-group
+ ng-repeat="(service, slices) in vm.projects | orderObjectByKey"
+ template-url="templates/accordion-group.html"
+ is-open="vm.accordion.open[service]"
+ heading="{{service}}">
+ <h4>Slices:</h4>
+ <a ng-repeat="(slice, resources) in slices"
+ ng-class="{active: slice === vm.selectedSlice}"
+ ng-click="vm.selectResources(resources, slice, service)"
+ href="#" class="list-group-item" >
+ {{slice}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>
+ </a>
+ </uib-accordion-group>
+ </uib-accordion>
</div>
- <div class="col-sm-4 animate-slide-left" ng-hide="!vm.selectedResources">
- <div class="list-group">
- <div class="list-group-item">
- <h2>Resources</h2>
- </div>
- <a href="#" ng-click="vm.selectMeters(meters, resource)" class="list-group-item" ng-repeat="(resource, meters) in vm.selectedResources" ng-class="{active: resource === vm.selectedResource}">
- {{resource}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>
- </a>
- </div>
- </div>
- <div class="col-sm-4 animate-slide-left" ng-hide="!vm.selectedMeters">
- <div class="list-group">
- <div class="list-group-item">
- <h2>Meters</h2>
- </div>
- <div class="list-group-item">
- <div class="row">
- <div class="col-xs-4">
- <label>Name:</label>
+ <section class="side-container col-sm-9">
+ <div class="row">
+ <article ng-hide="!vm.showStats" class="stats animate-slide-left">
+ <div class="col-xs-12">
+ <div class="list-group">
+ <div class="list-group-item">
+ <h3>Stats</h3>
+ </div>
+ <div class="list-group-item">
+ <ceilometer-stats ng-if="vm.selectedSlice" name="vm.selectedSlice"></ceilometer-stats>
+ </div>
</div>
- <div class="col-xs-4">
- <label>Unit:</label>
- </div>
- <div class="col-xs-4"></div>
</div>
- <div class="row" ng-click="vm.selectMeters(meters)" ng-repeat="meter in vm.selectedMeters" style="margin-bottom: 10px;">
- <div class="col-xs-4">
- {{meter.name}}
- </div>
- <div class="col-xs-4">
- {{meter.unit}}
- </div>
- <div class="col-xs-4">
- <a ui-sref="samples({name: meter.name, tenant: meter.resource_id})" class="btn btn-primary">
- <i class="glyphicon glyphicon-search"></i>
+ </article>
+ <article ng-hide="vm.showStats" class="meters animate-slide-left">
+ <div class="col-sm-4 animate-slide-left" ng-hide="!vm.selectedResources">
+ <div class="list-group">
+ <div class="list-group-item">
+ <h3>Resources</h3>
+ </div>
+ <a href="#"
+ ng-click="vm.selectMeters(meters, resource)"
+ class="list-group-item"
+ ng-repeat="(resource, meters) in vm.selectedResources"
+ ng-class="{active: resource === vm.selectedResource}">
+ {{resource}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>
</a>
</div>
</div>
- </div>
+ <div class="col-sm-8 animate-slide-left" ng-hide="!vm.selectedMeters">
+ <div class="list-group">
+ <div class="list-group-item">
+ <h3>Meters</h3>
+ </div>
+ <div class="list-group-item">
+ <div class="row">
+ <div class="col-xs-6">
+ <label>Name:</label>
+ </div>
+ <div class="col-xs-3">
+ <label>Unit:</label>
+ </div>
+ <div class="col-xs-3"></div>
+ </div>
+ <div class="row" ng-repeat="meter in vm.selectedMeters" style="margin-bottom: 10px;">
+ <div class="col-xs-6">
+ {{meter.name}}
+ </div>
+ <div class="col-xs-3">
+ {{meter.unit}}
+ </div>
+ <div class="col-xs-3">
+ <a ui-sref="samples({name: meter.name, tenant: meter.project_id})" class="btn btn-primary">
+ <i class="glyphicon glyphicon-search"></i>
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </article>
</div>
- </div>
+ </section>
+ </div>
+</section>
+<section ng-if="!vm.loader && vm.error">
+ <div class="alert alert-danger">
+ {{vm.error}}
</div>
</section>
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html
index b2d92d7..b279123 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html
@@ -10,37 +10,45 @@
</a>
</div>
</div>
-<div class="row" ng-if="!vm.loader">
- <form class="form-inline col-xs-8" ng-submit="vm.addMeterToChart(vm.addMeterValue)">
- <select ng-model="vm.addMeterValue" class="form-control" ng-options="resource.id as resource.id for resource in vm.sampleLabels"></select>
- <button class="btn btn-success">
- <i class="glyphicon glyphicon-plus"></i> Add
- </button>
- </form>
- <div class="col-xs-4 text-right">
- <a ng-click="vm.chartType = 'line'" class="btn" ng-class="{'btn-default': vm.chartType != 'bar', 'btn-primary': vm.chartType == 'line'}">Lines</a>
- <a ng-click="vm.chartType = 'bar'" class="btn" ng-class="{'btn-default': vm.chartType != 'line', 'btn-primary': vm.chartType == 'bar'}">Bars</a>
- </div>
-</div>
-
<div class="row" ng-show="vm.loader">
<div class="col-xs-12">
<div class="loader">Loading</div>
</div>
</div>
-<div class="row" ng-if="!vm.loader">
- <div class="col-xs-12">
- <canvas ng-if="vm.chartType === 'line'" id="line" class="chart chart-line" chart-data="vm.chart.data" chart-options="{datasetFill: false}"
- chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">
- </canvas>
- <canvas ng-if="vm.chartType === 'bar'" id="bar" class="chart chart-bar" chart-data="vm.chart.data"
- chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">
- </canvas>
- <!-- <pre>{{vm.chartMeters | json}}</pre> -->
+<section ng-if="!vm.loader && !vm.error">
+ <div class="row">
+ <form class="form-inline col-xs-8" ng-submit="vm.addMeterToChart(vm.addMeterValue)">
+ <select ng-model="vm.addMeterValue" class="form-control" ng-options="resource.id as resource.name for resource in vm.sampleLabels"></select>
+ <button class="btn btn-success">
+ <i class="glyphicon glyphicon-plus"></i> Add
+ </button>
+ </form>
+ <div class="col-xs-4 text-right">
+ <a ng-click="vm.chartType = 'line'" class="btn" ng-class="{'btn-default': vm.chartType != 'bar', 'btn-primary': vm.chartType == 'line'}">Lines</a>
+ <a ng-click="vm.chartType = 'bar'" class="btn" ng-class="{'btn-default': vm.chartType != 'line', 'btn-primary': vm.chartType == 'bar'}">Bars</a>
+ </div>
</div>
-</div>
-<div class="row" ng-if="!vm.loader">
- <div class="col-xs-12">
- <a ng-click="vm.removeFromChart(meter)" class="btn btn-chart" ng-style="{'background-color': vm.chartColors[$index]}" ng-repeat="meter in vm.chartMeters">{{meter}}</a>
+ <div class="row" ng-if="!vm.loader">
+ <div class="col-xs-12">
+ <canvas ng-if="vm.chartType === 'line'" id="line" class="chart chart-line" chart-data="vm.chart.data" chart-options="{datasetFill: false}"
+ chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">
+ </canvas>
+ <canvas ng-if="vm.chartType === 'bar'" id="bar" class="chart chart-bar" chart-data="vm.chart.data"
+ chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">
+ </canvas>
+ <!-- <pre>{{vm.chartMeters | json}}</pre> -->
+ </div>
</div>
-</div>
\ No newline at end of file
+ <div class="row" ng-if="!vm.loader">
+ <div class="col-xs-12">
+ <a ng-click="vm.removeFromChart(meter)" class="btn btn-chart" ng-style="{'background-color': vm.chartColors[$index]}" ng-repeat="meter in vm.chartMeters">
+ {{meter.resource_name || meter.resource_id}}
+ </a>
+ </div>
+ </div>
+</section>
+<section ng-if="!vm.loader && vm.error">
+ <div class="alert alert-danger">
+ {{vm.error}}
+ </div>
+</section>
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-stats.tpl.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-stats.tpl.html
new file mode 100644
index 0000000..1f5ff11
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-stats.tpl.html
@@ -0,0 +1,29 @@
+<div ng-show="vm.loader" class="loader">Loading</div>
+
+<section ng-if="!vm.loader && !vm.error">
+
+ <div class="alert alert-danger" ng-if="vm.stats.length == 0">
+ No result
+ </div>
+
+ <table class="table" ng-if="vm.stats.length > 0">
+ <tr>
+ <th>Type:</th>
+ <th>Meter:</th>
+ <th>Unit:</th>
+ <th>Value:</th>
+ </tr>
+ <tr ng-repeat="item in vm.stats">
+ <td>{{item.category}}</td>
+ <td>{{item.meter}}</td>
+ <td>{{item.unit}}</td>
+ <td>{{item.value}}</td>
+ </tr>
+ </table>
+</section>
+
+<section ng-if="!vm.loader && vm.error">
+ <div class="alert alert-danger">
+ {{vm.error}}
+ </div>
+</section>
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/split.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/split.html
deleted file mode 100644
index 534d3d5..0000000
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/split.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<div id="one" class="split split-horizontal">
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, eos debitis repellendus corrupti vel dolores asperiores, ipsam voluptatibus nesciunt ipsum architecto harum magnam similique doloremque rerum illum. Magnam, nesciunt magni.
- Minus nostrum dolores perspiciatis dolorum eos? Sed, ad fugiat natus amet voluptas officiis, reiciendis tempora error quia repudiandae odit nisi distinctio atque ipsam iste officia ab porro et quo magni.
- Voluptatem ab rem necessitatibus nam voluptas quo, velit nobis id ea temporibus illum corrupti sequi, aperiam reprehenderit cum! Placeat quas quod minima expedita beatae totam numquam veritatis adipisci doloremque, sit.
- Suscipit doloremque voluptatum maiores architecto ipsa quis, nihil provident totam, quos qui. Ipsa quibusdam sit, cumque eum provident ratione molestiae quia in ex! Rem voluptates officiis aperiam ullam dignissimos sequi.
- Ad sed quasi et, dolorem autem perferendis dolor. Cupiditate nemo delectus minus sint mollitia accusantium odio, explicabo nihil illum ut possimus ducimus! Recusandae excepturi, est deleniti accusamus aut quasi. Sit!
-</div>
-<div id="two" class="split split-horizontal">
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit accusamus laboriosam, quo, ipsa quisquam, neque alias animi esse quia, doloremque nulla nihil. Id aliquid necessitatibus atque eum, fugit sed nobis!
- Blanditiis ab earum placeat tenetur in eos, omnis quidem accusantium voluptate corporis, labore, cum voluptatibus totam sunt mollitia et rerum sit. Voluptatem fugiat eaque dolore explicabo ex veritatis deleniti delectus.
- Nobis aliquam blanditiis cumque nesciunt repellendus voluptate ullam, eligendi dicta voluptates tenetur molestias omnis itaque eius voluptas dignissimos inventore repellat distinctio velit ducimus ipsam placeat. Quo amet aut, doloremque incidunt.
- Asperiores sed cupiditate animi aliquam, facilis vitae nobis deserunt ipsa fugiat, at incidunt eum delectus error inventore itaque fuga sunt aspernatur beatae saepe maxime id. Fuga consequatur hic debitis ipsum.
- Animi dolorum ullam, dolorem ut quibusdam tempora repellendus iste veritatis doloribus nam? Minima veritatis omnis deleniti illo? Vero, perferendis ipsum, ea dicta illum non reiciendis obcaecati sunt dolorem esse hic.
-</div>
-<div id="three" class="split split-horizontal">
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatem quod expedita vero voluptatibus modi, dolores assumenda ex atque aliquam accusamus, deserunt quibusdam pariatur eaque optio ducimus minima. Commodi, odit. Nulla.
- Rerum, nostrum, officiis! Nam vel in ea ut et nemo quae quis suscipit dolores voluptatum odio, qui ratione dolor vero perspiciatis enim incidunt error harum hic ad numquam nostrum magni.
- Minus illo vel ipsa, ullam unde itaque cum mollitia nihil! Voluptatibus quaerat ab ut quo, repudiandae qui reprehenderit eligendi maiores harum labore sit, laudantium expedita reiciendis hic nostrum beatae id!
- Laborum magni iusto sunt commodi dolor quis voluptatibus fugiat alias, aliquid fugit nisi facere. Eaque harum laudantium sint, veniam laborum illum beatae cumque quis reprehenderit tempore, animi perferendis officiis quos.
- Quam iusto id necessitatibus nam asperiores quod inventore itaque ullam laborum quis. Excepturi, suscipit, autem! Pariatur commodi nisi quia, sit perspiciatis necessitatibus, tempore neque nulla nemo eum aspernatur placeat voluptate!
-</div>
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/teone@clnode015.clemson.cloudlab.us b/xos/core/xoslib/ngXosViews/ceilometerDashboard/teone@clnode015.clemson.cloudlab.us
new file mode 100644
index 0000000..8e990a2
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/teone@clnode015.clemson.cloudlab.us
@@ -0,0 +1,20 @@
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1, max-scale=1">
+<!-- browserSync -->
+
+<!-- inject:css -->
+<link rel="stylesheet" href="/css/ceilometerDashboard.css">
+<link rel="stylesheet" href="/css/dev.css">
+<!-- endinject -->
+<link rel="stylesheet" href="css/ceilometerDashboard.css">
+<div id="xosCeilometerDashboard">
+ <div ui-view ng-class="stateName"></div>
+</div>
+
+
+<script src="vendor/ui.bootstrap/src/collapse/collapse.js"></script>
+<script src="vendor/ui.bootstrap/src/accordion/accordion.js"></script>
+<!-- inject:js -->
+<script src="/../../static/js/vendor/xosCeilometerDashboardVendor.js"></script>
+<script src="/../../static/js/xosCeilometerDashboard.js"></script>
+<!-- endinject -->
diff --git a/xos/core/xoslib/static/css/xosCeilometerDashboard.css b/xos/core/xoslib/static/css/xosCeilometerDashboard.css
new file mode 100644
index 0000000..8aad3b2
--- /dev/null
+++ b/xos/core/xoslib/static/css/xosCeilometerDashboard.css
@@ -0,0 +1 @@
+#xosCeilometerDashboard{position:relative}.panel{margin-top:10px}.panel-body:not(:first-child){border-top:1px solid #e3e3e3}.panel-body .row{margin-top:10px}.chart{width:100%;height:300px}.btn-chart,.btn-chart:hover{color:#fff}.side-container{position:relative}.service-list{margin-top:-10px}.service-list h3{margin-top:0;margin-bottom:0}.service-list a{text-decoration:none;color:#333}.meters,.stats{margin-top:25px;position:absolute;top:0;left:0;width:100%}.loader{font-size:10px;margin:150px auto;text-indent:-9999em;width:11em;height:11em;border-radius:50%;background:#fff;background:linear-gradient(to right,#fff 10%,rgba(255,255,255,0) 42%);position:relative;animation:load3 1.4s infinite linear;transform:translateZ(0)}.loader:before{width:50%;height:50%;background:#105e9e;border-radius:100% 0 0;position:absolute;top:0;left:0;content:''}.loader:after{background:#fff;width:75%;height:75%;border-radius:50%;content:'';margin:auto;position:absolute;top:0;left:0;bottom:0;right:0}@keyframes load3{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}[ui-view]{position:absolute;top:0;bottom:0;width:100%}[ui-view].ceilometerDashboard.ng-leave{animation:1s bounceOutLeft ease}[ui-view].samples.ng-enter{animation:1s bounceInRight ease}[ui-view].samples.ng-leave{animation:1s bounceOutRight ease}[ui-view].ceilometerDashboard.ng-enter{animation:1s bounceInLeft ease}.animate .animate-slide-left.ng-hide-remove{animation:.5s bounceInRight ease}.animate .animate-slide-left.ng-hide-add{animation:.5s bounceOutRight ease}@keyframes bounceInRight{from,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}from{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}@keyframes bounceInLeft{from,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}@keyframes slideInUp{from{transform:translate3d(0,100%,0);visibility:visible}to{transform:translate3d(0,0,0)}}@keyframes bounceOutRight{20%{opacity:1;transform:translate3d(-20px,0,0)}to{opacity:0;transform:translate3d(2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;transform:translate3d(20px,0,0)}to{opacity:0;transform:translate3d(-2000px,0,0)}}@keyframes slideOutDown{from{transform:translate3d(0,0,0)}to{visibility:hidden;transform:translate3d(0,100%,0)}}
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/vendor/xosCeilometerDashboardVendor.js b/xos/core/xoslib/static/js/vendor/xosCeilometerDashboardVendor.js
index 551df45..13dde32 100644
--- a/xos/core/xoslib/static/js/vendor/xosCeilometerDashboardVendor.js
+++ b/xos/core/xoslib/static/js/vendor/xosCeilometerDashboardVendor.js
@@ -1,2 +1,3 @@
-(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;var i=function(t,i){return t["offset"+i]?t["offset"+i]:document.defaultView.getComputedStyle(t).getPropertyValue(i)},e=this.width=i(t.canvas,"Width"),n=this.height=i(t.canvas,"Height");t.canvas.width=e,t.canvas.height=n;var e=this.width=t.canvas.width,n=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n<t.length;n++)i.apply(e,[t[n],n].concat(s))}else for(var o in t)i.apply(e,[t[o],o].concat(s))},o=s.clone=function(t){var i={};return n(t,function(e,s){t.hasOwnProperty(s)&&(i[s]=e)}),i},a=s.extend=function(t){return n(Array.prototype.slice.call(arguments,1),function(i){n(i,function(e,s){i.hasOwnProperty(s)&&(t[s]=e)})}),t},h=s.merge=function(t,i){var e=Array.prototype.slice.call(arguments,0);return e.unshift({}),a.apply(null,e)},l=s.indexOf=function(t,i){if(Array.prototype.indexOf)return t.indexOf(i);for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1},r=(s.where=function(t,i){var e=[];return s.each(t,function(t){i(t)&&e.push(t)}),e},s.findNextWhere=function(t,i,e){e||(e=-1);for(var s=e+1;s<t.length;s++){var n=t[s];if(i(n))return n}},s.findPreviousWhere=function(t,i,e){e||(e=t.length);for(var s=e-1;s>=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof define&&define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},v=s.min=function(t){return Math.min.apply(Math,t)},m=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),y=s.radians=function(t){return t*(Math.PI/180)},C=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),x=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),S=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=v(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=x(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,m=Math.pow(10,u),y=Math.round(f/m);(y>a||a>2*y)&&!h;)if(y>a)m*=2,y=Math.round(f/m),y%1!==0&&(h=!0);else if(n&&u>=0){if(m/2%1!==0)break;m/=2,y=Math.round(f/m)}else m/=2,y=Math.round(f/m);return h&&(y=o,m=f/y),{steps:y,stepValue:m,min:p,max:p+y*m}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),w=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=S(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),-(s*Math.pow(2,10*(t-=1))*Math.sin((1*t-i)*(2*Math.PI)/e)))},easeOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),s*Math.pow(2,-10*t)*Math.sin((1*t-i)*(2*Math.PI)/e)+1)},easeInOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:2==(t/=.5)?1:(e||(e=1*(.3*1.5)),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),1>t?-.5*(s*Math.pow(2,10*(t-=1))*Math.sin((1*t-i)*(2*Math.PI)/e)):s*Math.pow(2,-10*(t-=1))*Math.sin((1*t-i)*(2*Math.PI)/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*(t*t*(((i*=1.525)+1)*t-i)):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-w.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?1*(7.5625*t*t):2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*w.easeInBounce(2*t):.5*w.easeOutBounce(2*t-1)+.5}}),b=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),L=(s.animationLoop=function(t,i,e,s,n,o){var a=0,h=w[e]||w.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=b(l):n.apply(o)};b(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),k=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},F=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},L(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){k(t.chart.canvas,e,i)})}),A=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},R=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},T=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),M=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},W=s.fontString=function(t,i,e){return i+" "+t+"px "+e},z=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},B=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return M(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=A(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:R(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,T(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return S(this.options.legendTemplate,this)},destroy:function(){this.clear(),F(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(t){var i,e,n,o,a,l=[],r=[],d=[];return s.each(this.datasets,function(t){i=t.points||t.bars||t.segments,i[h]&&i[h].hasValue()&&l.push(i[h])}),s.each(l,function(t){r.push(t.x),d.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),a=v(d),n=g(d),o=v(r),e=g(r),{x:o>this.chart.width/2?o:e,y:(a+n)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:S(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)<Math.pow(e,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),e.Arc=e.Element.extend({inRange:function(t,i){var e=s.getAngleFromPoint(this,{x:t,y:i}),n=e.angle>=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=this.caretPadding=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}B(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=W(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=z(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{B(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=m(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(S(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?z(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()},calculateXLabelRotation:function(){this.ctx.font=this.font;var t,i,e=this.ctx.measureText(this.xLabels[0]).width,s=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=s/2+3,this.xScalePaddingLeft=e/2>this.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=z(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(y(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(y(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),l&&(t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+C(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+C(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==e||a||(a=!0),a&&t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*y(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=v([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=m(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(S(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=v([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;i<this.valuesCount;i++)t=this.getPointPosition(i,d),e=this.ctx.measureText(S(this.templateString,{value:this.labels[i]})).width+5,0===i||i===this.valuesCount/2?(s=e/2,t.x+s>p&&(p=t.x+s,n=i),t.x-s<g&&(g=t.x-s,a=i)):i<this.valuesCount/2?t.x+e>p&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e<g&&(g=t.x-e,a=i);l=g,r=Math.ceil(p-this.width),o=this.getIndexAngle(n),h=this.getIndexAngle(a),c=r/Math.sin(o+Math.PI/2),u=l/Math.sin(h+Math.PI/2),c=f(c)?c:0,u=f(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,i){var e=this.width-i-this.drawingArea,s=t+this.drawingArea;this.xCenter=(s+e)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var i=2*Math.PI/this.valuesCount;return t*i-Math.PI/2},getPointPosition:function(t,i){var e=this.getIndexAngle(t);return{x:Math.cos(e)*i+this.xCenter,y:Math.sin(e)*i+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(n(this.yLabels,function(i,e){if(e>0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)s=this.getPointPosition(a,this.calculateCenterOffset(this.min+e*this.stepValue)),0===a?t.moveTo(s.x,s.y):t.lineTo(s.x,s.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var h=t.measureText(i).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-h/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,h+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(i,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var i=this.valuesCount-1;i>=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;0===i?t.textAlign="center":i===a?t.textAlign="center":a>i?t.textAlign="left":t.textAlign="right",r?t.textBaseline="middle":l?t.textBaseline="bottom":t.textBaseline="top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i,s){var n={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(n),e.each(i.data,function(e,s){n.bars.push(new this.BarClass({value:e,label:t.labels[s],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<this.datasets.length;a++)for(i=0;i<this.datasets[a].bars.length;i++)if(this.datasets[a].bars[i].inRange(n.x,n.y))return e.each(this.datasets,o),s;return s},buildScale:function(t){var i=this,s=function(){var t=[];return i.eachBars(function(i){t.push(i.value)}),t},n={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(n,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(n)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].bars.push(new this.BarClass({value:t,label:i,x:this.scale.calculateBarX(this.datasets.length,e,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),
-base:this.scale.endPoint,strokeColor:this.datasets[e].strokeColor,fillColor:this.datasets[e].fillColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle)},this)}}),i.types.Doughnut.extend({name:"Pie",defaults:e.merge(s,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,i){e.extend(t,{x:this.scale.calculateX(i),y:this.scale.endPoint}),t.save()},this)},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.datasets,function(t){e.each(t.points,function(t){t.inRange(s.x,s.y)&&i.push(t)})},this),i},buildScale:function(t){var s=this,n=function(){var t=[];return s.eachPoints(function(i){t.push(i.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(o,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new i.Scale(o)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();var s=this.chart.ctx,n=function(t){return null!==t.value},o=function(t,i,s){return e.findNextWhere(i,n,s)||t},a=function(t,i,s){return e.findPreviousWhere(i,n,s)||t};this.scale.draw(i),e.each(this.datasets,function(t){var h=e.where(t.points,n);e.each(t.points,function(t,e){t.hasValue()&&t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(e)},i)},this),this.options.bezierCurve&&e.each(h,function(t,i){var s=i>0&&i<h.length-1?this.options.bezierCurveTension:0;t.controlPoints=e.splineCurve(a(t,h,i),t,o(t,h,i),s),t.controlPoints.outer.y>this.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.y<this.scale.startPoint&&(t.controlPoints.outer.y=this.scale.startPoint),t.controlPoints.inner.y>this.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y<this.scale.startPoint&&(t.controlPoints.inner.y=this.scale.startPoint)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(h,function(t,i){if(0===i)s.moveTo(t.x,t.y);else if(this.options.bezierCurve){var e=a(t,h,i);s.bezierCurveTo(e.controlPoints.outer.x,e.controlPoints.outer.y,t.controlPoints.inner.x,t.controlPoints.inner.y,t.x,t.y)}else s.lineTo(t.x,t.y)},this),s.stroke(),this.options.datasetFill&&h.length>0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers;i.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this),function(t){"use strict";"object"==typeof exports?module.exports=t(angular,Chart):"function"==typeof define&&define.amd?define(["angular","chart"],t):t(angular,Chart)}(function(t,i){"use strict";function e(){var e={},s={Chart:i,getOptions:function(i){var s=i&&e[i]||{};return t.extend({},e,s)}};this.setOptions=function(i,s){return s?void(e[i]=t.extend(e[i]||{},s)):(s=i,void(e=t.extend(e,s)))},this.$get=function(){return s}}function s(e,s){function o(t,i){return t&&i&&t.length&&i.length?Array.isArray(t[0])?t.length===i.length&&t.every(function(t,e){return t.length===i[e].length}):i.reduce(a,0)>0?t.length===i.length:!1:!1}function a(t,i){return t+i}function h(i,e,s,n){var o=null;return function(a){var h=e.getPointsAtEvent||e.getBarsAtEvent||e.getSegmentsAtEvent;if(h){var l=h.call(e,a);(n===!1||t.equals(o,l)===!1)&&(o=l,i[s](l,a),i.$apply())}}}function l(s,n){for(var o=t.copy(n.colours||e.getOptions(s).colours||i.defaults.global.colours);o.length<n.data.length;)o.push(n.getColour());return o.map(r)}function r(t){return"object"==typeof t&&null!==t?t:"string"==typeof t&&"#"===t[0]?u(f(t.substr(1))):c()}function c(){var t=[d(0,255),d(0,255),d(0,255)];return u(t)}function u(t){return{fillColor:p(t,.2),strokeColor:p(t,1),pointColor:p(t,1),pointStrokeColor:"#fff",pointHighlightFill:"#fff",pointHighlightStroke:p(t,.8)}}function d(t,i){return Math.floor(Math.random()*(i-t+1))+t}function p(t,i){return n?"rgb("+t.join(",")+")":"rgba("+t.concat(i).join(",")+")"}function f(t){var i=parseInt(t,16),e=i>>16&255,s=i>>8&255,n=255&i;return[e,s,n]}function g(i,e,s,n){return{labels:i,datasets:e.map(function(i,e){return t.extend({},n[e],{label:s[e],data:i})})}}function v(i,e,s){return i.map(function(i,n){return t.extend({},s[n],{label:i,value:e[n],color:s[n].strokeColor,highlight:s[n].pointHighlightStroke})})}function m(t,i){var e=t.parent(),s=e.find("chart-legend"),n="<chart-legend>"+i.generateLegend()+"</chart-legend>";s.length?s.replaceWith(n):e.append(n)}function y(t,i,e,s){Array.isArray(e.data[0])?t.datasets.forEach(function(t,e){(t.points||t.bars).forEach(function(t,s){t.value=i[e][s]})}):t.segments.forEach(function(t,e){t.value=i[e]}),t.update(),e.$emit("update",t),e.legend&&"false"!==e.legend&&m(s,t)}function C(t){return!t||Array.isArray(t)&&!t.length||"object"==typeof t&&!Object.keys(t).length}function x(s,n){var o=t.extend({},i.defaults.global,e.getOptions(s),n.options);return o.responsive}return function(i){return{restrict:"CA",scope:{data:"=?",labels:"=?",options:"=?",series:"=?",colours:"=?",getColour:"=?",chartType:"=",legend:"@",click:"=?",hover:"=?",chartData:"=?",chartLabels:"=?",chartOptions:"=?",chartSeries:"=?",chartColours:"=?",chartLegend:"@",chartClick:"=?",chartHover:"=?"},link:function(a,r){function u(t,i){a.$watch(t,function(t){"undefined"!=typeof t&&(a[i]=t)})}function d(e,s){if(!C(e)&&!t.equals(e,s)){var n=i||a.chartType;n&&(S&&S.destroy(),p(n))}}function p(i){if(x(i,a)&&0===r[0].clientHeight&&0===w.clientHeight)return s(function(){p(i)},50,!1);if(a.data&&a.data.length){a.getColour="function"==typeof a.getColour?a.getColour:c,a.colours=l(i,a);var n=r[0],o=n.getContext("2d"),u=Array.isArray(a.data[0])?g(a.labels,a.data,a.series||[],a.colours):v(a.labels,a.data,a.colours),d=t.extend({},e.getOptions(i),a.options);S=new e.Chart(o)[i](u,d),a.$emit("create",S),n.onclick=a.click?h(a,S,"click",!1):t.noop,n.onmousemove=a.hover?h(a,S,"hover",!0):t.noop,a.legend&&"false"!==a.legend&&m(r,S)}}function f(t){if("undefined"!=typeof console&&"test"!==e.getOptions().env){var i="function"==typeof console.warn?console.warn:console.log;a[t]&&i.call(console,'"%s" is deprecated and will be removed in a future version. Please use "chart-%s" instead.',t,t)}}var S,w=document.createElement("div");w.className="chart-container",r.replaceWith(w),w.appendChild(r[0]),n&&window.G_vmlCanvasManager.initElement(r[0]),["data","labels","options","series","colours","legend","click","hover"].forEach(f),u("chartData","data"),u("chartLabels","labels"),u("chartOptions","options"),u("chartSeries","series"),u("chartColours","colours"),u("chartLegend","legend"),u("chartClick","click"),u("chartHover","hover"),a.$watch("data",function(t,e){if(t&&t.length&&(!Array.isArray(t[0])||t[0].length)){var s=i||a.chartType;if(s){if(S){if(o(t,e))return y(S,t,a,r);S.destroy()}p(s)}}},!0),a.$watch("series",d,!0),a.$watch("labels",d,!0),a.$watch("options",d,!0),a.$watch("colours",d,!0),a.$watch("chartType",function(i,e){C(i)||t.equals(i,e)||(S&&S.destroy(),p(i))}),a.$on("$destroy",function(){S&&S.destroy()})}}}}i.defaults.global.responsive=!0,i.defaults.global.multiTooltipTemplate="<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>",i.defaults.global.colours=["#97BBCD","#DCDCDC","#F7464A","#46BFBD","#FDB45C","#949FB1","#4D5360"];var n="object"==typeof window.G_vmlCanvasManager&&null!==window.G_vmlCanvasManager&&"function"==typeof window.G_vmlCanvasManager.initElement;return n&&(i.defaults.global.animation=!1),t.module("chart.js",[]).provider("ChartJs",e).factory("ChartJsFactory",["ChartJs","$timeout",s]).directive("chartBase",["ChartJsFactory",function(t){return new t}]).directive("chartLine",["ChartJsFactory",function(t){return new t("Line")}]).directive("chartBar",["ChartJsFactory",function(t){return new t("Bar")}]).directive("chartRadar",["ChartJsFactory",function(t){return new t("Radar")}]).directive("chartDoughnut",["ChartJsFactory",function(t){return new t("Doughnut")}]).directive("chartPie",["ChartJsFactory",function(t){return new t("Pie")}]).directive("chartPolarArea",["ChartJsFactory",function(t){return new t("PolarArea")}])});
\ No newline at end of file
+(function(){"use strict";var t=this,e=t.Chart,i=function(t){this.canvas=t.canvas,this.ctx=t;var e=function(t,e){return t["offset"+e]?t["offset"+e]:document.defaultView.getComputedStyle(t).getPropertyValue(e)},i=this.width=e(t.canvas,"Width"),s=this.height=e(t.canvas,"Height");t.canvas.width=i,t.canvas.height=s;var i=this.width=t.canvas.width,s=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,n.retinaScale(this),this};i.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},i.types={};var n=i.helpers={},s=n.each=function(t,e,i){var n=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var s;for(s=0;s<t.length;s++)e.apply(i,[t[s],s].concat(n))}else for(var o in t)e.apply(i,[t[o],o].concat(n))},o=n.clone=function(t){var e={};return s(t,function(i,n){t.hasOwnProperty(n)&&(e[n]=i)}),e},a=n.extend=function(t){return s(Array.prototype.slice.call(arguments,1),function(e){s(e,function(i,n){e.hasOwnProperty(n)&&(t[n]=i)})}),t},r=n.merge=function(t,e){var i=Array.prototype.slice.call(arguments,0);return i.unshift({}),a.apply(null,i)},l=n.indexOf=function(t,e){if(Array.prototype.indexOf)return t.indexOf(e);for(var i=0;i<t.length;i++)if(t[i]===e)return i;return-1},h=(n.where=function(t,e){var i=[];return n.each(t,function(t){e(t)&&i.push(t)}),i},n.findNextWhere=function(t,e,i){i||(i=-1);for(var n=i+1;n<t.length;n++){var s=t[n];if(e(s))return s}},n.findPreviousWhere=function(t,e,i){i||(i=t.length);for(var n=i-1;n>=0;n--){var s=t[n];if(e(s))return s}},n.inherits=function(t){var e=this,i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},n=function(){this.constructor=i};return n.prototype=e.prototype,i.prototype=new n,i.extend=h,t&&a(i.prototype,t),i.__super__=e.prototype,i}),c=n.noop=function(){},u=n.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=n.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},f=n.amd="function"==typeof define&&define.amd,p=n.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=n.max=function(t){return Math.max.apply(Math,t)},v=n.min=function(t){return Math.min.apply(Math,t)},m=(n.cap=function(t,e,i){if(p(e)){if(t>e)return e}else if(p(i)&&i>t)return i;return t},n.getDecimalPlaces=function(t){return t%1!==0&&p(t)?t.toString().split(".")[1].length:0}),C=n.radians=function(t){return t*(Math.PI/180)},y=(n.getAngleFromPoint=function(t,e){var i=e.x-t.x,n=e.y-t.y,s=Math.sqrt(i*i+n*n),o=2*Math.PI+Math.atan2(n,i);return 0>i&&0>n&&(o+=2*Math.PI),{angle:o,distance:s}},n.aliasPixel=function(t){return t%2===0?0:.5}),b=(n.splineCurve=function(t,e,i,n){var s=Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2)),o=Math.sqrt(Math.pow(i.x-e.x,2)+Math.pow(i.y-e.y,2)),a=n*s/(s+o),r=n*o/(s+o);return{inner:{x:e.x-a*(i.x-t.x),y:e.y-a*(i.y-t.y)},outer:{x:e.x+r*(i.x-t.x),y:e.y+r*(i.y-t.y)}}},n.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),w=(n.calculateScaleRange=function(t,e,i,n,s){var o=2,a=Math.floor(e/(1.5*i)),r=o>=a,l=g(t),h=v(t);l===h&&(l+=.5,h>=.5&&!n?h-=.5:l+=.5);for(var c=Math.abs(l-h),u=b(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),f=n?0:Math.floor(h/(1*Math.pow(10,u)))*Math.pow(10,u),p=d-f,m=Math.pow(10,u),C=Math.round(p/m);(C>a||a>2*C)&&!r;)if(C>a)m*=2,C=Math.round(p/m),C%1!==0&&(r=!0);else if(s&&u>=0){if(m/2%1!==0)break;m/=2,C=Math.round(p/m)}else m/=2,C=Math.round(p/m);return r&&(C=o,m=p/C),{steps:C,stepValue:m,min:f,max:f+C*m}},n.template=function(t,e){function i(t,e){var i=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):n[t]=n[t];return e?i(e):i}if(t instanceof Function)return t(e);var n={};return i(t,e)}),x=(n.generateLabels=function(t,e,i,n){var o=new Array(e);return labelTemplateString&&s(o,function(e,s){o[s]=w(t,{value:i+n*(s+1)})}),o},n.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1==(t/=1)?1:(i||(i=.3),n<Math.abs(1)?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),-(n*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)))},easeOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1==(t/=1)?1:(i||(i=.3),n<Math.abs(1)?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),n*Math.pow(2,-10*t)*Math.sin((1*t-e)*(2*Math.PI)/i)+1)},easeInOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:2==(t/=.5)?1:(i||(i=1*(.3*1.5)),n<Math.abs(1)?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),1>t?-.5*(n*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)):n*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*t+e)+2)},easeInBounce:function(t){return 1-x.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?1*(7.5625*t*t):2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*x.easeInBounce(2*t):.5*x.easeOutBounce(2*t-1)+.5}}),S=n.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=n.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),k=(n.animationLoop=function(t,e,i,n,s,o){var a=0,r=x[i]||x.linear,l=function(){a++;var i=a/e,h=r(i);t.call(o,h,i,a),n.call(o,h,i),e>a?o.animationFrame=S(l):s.apply(o)};S(l)},n.getRelativePosition=function(t){var e,i,n=t.originalEvent||t,s=t.currentTarget||t.srcElement,o=s.getBoundingClientRect();return n.touches?(e=n.touches[0].clientX-o.left,i=n.touches[0].clientY-o.top):(e=n.clientX-o.left,i=n.clientY-o.top),{x:e,y:i}},n.addEvent=function(t,e,i){t.addEventListener?t.addEventListener(e,i):t.attachEvent?t.attachEvent("on"+e,i):t["on"+e]=i}),A=n.removeEvent=function(t,e,i){t.removeEventListener?t.removeEventListener(e,i,!1):t.detachEvent?t.detachEvent("on"+e,i):t["on"+e]=c},L=(n.bindEvents=function(t,e,i){t.events||(t.events={}),s(e,function(e){t.events[e]=function(){i.apply(t,arguments)},k(t.chart.canvas,e,t.events[e])})},n.unbindEvents=function(t,e){s(e,function(e,i){A(t.chart.canvas,i,e)})}),$=n.getMaximumWidth=function(t){var e=t.parentNode;return e.clientWidth},F=n.getMaximumHeight=function(t){var e=t.parentNode;return e.clientHeight},T=(n.getMaximumSize=n.getMaximumWidth,n.retinaScale=function(t){var e=t.ctx,i=t.canvas.width,n=t.canvas.height;window.devicePixelRatio&&(e.canvas.style.width=i+"px",e.canvas.style.height=n+"px",e.canvas.height=n*window.devicePixelRatio,e.canvas.width=i*window.devicePixelRatio,e.scale(window.devicePixelRatio,window.devicePixelRatio))}),R=n.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},D=n.fontString=function(t,e,i){return e+" "+t+"px "+i},M=n.longestText=function(t,e,i){t.font=e;var n=0;return s(i,function(e){var i=t.measureText(e).width;n=i>n?i:n}),n},W=n.drawRoundedRectangle=function(t,e,i,n,s,o){t.beginPath(),t.moveTo(e+o,i),t.lineTo(e+n-o,i),t.quadraticCurveTo(e+n,i,e+n,i+o),t.lineTo(e+n,i+s-o),t.quadraticCurveTo(e+n,i+s,e+n-o,i+s),t.lineTo(e+o,i+s),t.quadraticCurveTo(e,i+s,e,i+s-o),t.lineTo(e,i+o),t.quadraticCurveTo(e,i,e+o,i),t.closePath()};i.instances={},i.Type=function(t,e,n){this.options=e,this.chart=n,this.id=u(),i.instances[this.id]=this,e.responsive&&this.resize(),this.initialize.call(this,t)},a(i.Type.prototype,{initialize:function(){return this},clear:function(){return R(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var e=this.chart.canvas,i=$(this.chart.canvas),n=this.options.maintainAspectRatio?i/this.chart.aspectRatio:F(this.chart.canvas);return e.width=this.chart.width=i,e.height=this.chart.height=n,T(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?n.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return w(this.options.legendTemplate,this)},destroy:function(){this.clear(),L(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete i.instances[this.id]},showTooltip:function(t,e){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var e=!1;return t.length!==this.activeElements.length?e=!0:(s(t,function(t,i){t!==this.activeElements[i]&&(e=!0)},this),e)}.call(this,t);if(o||e){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,r,h=this.datasets.length-1;h>=0&&(a=this.datasets[h].points||this.datasets[h].bars||this.datasets[h].segments,r=l(a,t[0]),-1===r);h--);var c=[],u=[],d=function(t){var e,i,s,o,a,l=[],h=[],d=[];return n.each(this.datasets,function(t){e=t.points||t.bars||t.segments,e[r]&&e[r].hasValue()&&l.push(e[r])}),n.each(l,function(t){h.push(t.x),d.push(t.y),c.push(n.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),a=v(d),s=g(d),o=v(h),i=g(h),{x:o>this.chart.width/2?o:i,y:(a+s)/2}}.call(this,r);new i.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else s(t,function(t){var e=t.tooltipPosition();new i.Tooltip({x:Math.round(e.x),y:Math.round(e.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:w(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),i.Type.extend=function(t){var e=this,n=function(){return e.apply(this,arguments)};if(n.prototype=o(e.prototype),a(n.prototype,t),n.extend=i.Type.extend,t.name||e.prototype.name){var s=t.name||e.prototype.name,l=i.defaults[e.prototype.name]?o(i.defaults[e.prototype.name]):{};i.defaults[s]=a(l,t.defaults),i.types[s]=n,i.prototype[s]=function(t,e){var o=r(i.defaults.global,i.defaults[s],e||{});return new n(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return e},i.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(i.Element.prototype,{initialize:function(){},restore:function(t){return t?s(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return s(t,function(t,e){this._saved[e]=this[e],this[e]=t},this),this},transition:function(t,e){return s(t,function(t,i){this[i]=(t-this._saved[i])*e+this._saved[i]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return p(this.value)}}),i.Element.extend=h,i.Point=i.Element.extend({display:!0,inRange:function(t,e){var i=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(e-this.y,2)<Math.pow(i,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),i.Arc=i.Element.extend({inRange:function(t,e){var i=n.getAngleFromPoint(this,{x:t,y:e}),s=i.angle>=this.startAngle&&i.angle<=this.endAngle,o=i.distance>=this.innerRadius&&i.distance<=this.outerRadius;return s&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,e=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*e,y:this.y+Math.sin(t)*e}},draw:function(t){var e=this.ctx;e.beginPath(),e.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),e.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),e.closePath(),e.strokeStyle=this.strokeColor,e.lineWidth=this.strokeWidth,e.fillStyle=this.fillColor,e.fill(),e.lineJoin="bevel",this.showStroke&&e.stroke()}}),i.Rectangle=i.Element.extend({draw:function(){var t=this.ctx,e=this.width/2,i=this.x-e,n=this.x+e,s=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(i+=o,n-=o,s+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(i,this.base),t.lineTo(i,s),t.lineTo(n,s),t.lineTo(n,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,e){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&e>=this.y&&e<=this.base}}),i.Tooltip=i.Element.extend({draw:function(){var t=this.chart.ctx;t.font=D(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var e=this.caretPadding=2,i=t.measureText(this.text).width+2*this.xPadding,n=this.fontSize+2*this.yPadding,s=n+this.caretHeight+e;this.x+i/2>this.chart.width?this.xAlign="left":this.x-i/2<0&&(this.xAlign="right"),this.y-s<0&&(this.yAlign="below");var o=this.x-i/2,a=this.y-s;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-e),t.lineTo(this.x+this.caretHeight,this.y-(e+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(e+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+e+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+e),t.lineTo(this.x+this.caretHeight,this.y+e+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+e+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-i+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}W(t,o,a,i,n,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+i/2,a+n/2)}}}),i.MultiTooltip=i.Element.extend({initialize:function(){this.font=D(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=D(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,e=M(this.ctx,this.font,this.labels)+this.fontSize+3,i=g([e,t]);this.width=i+2*this.xPadding;var n=this.height/2;this.y-n<0?this.y=n:this.y+n>this.chart.height&&(this.y=this.chart.height-n),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var e=this.y-this.height/2+this.yPadding,i=t-1;return 0===t?e+this.titleFontSize/2:e+(1.5*this.fontSize*i+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{W(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,n.each(this.labels,function(e,i){t.fillStyle=this.textColor,t.fillText(e,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(i+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(i+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[i].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(i+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),i.Scale=i.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=m(this.stepValue),e=0;e<=this.steps;e++)this.yLabels.push(w(this.templateString,{value:(this.min+e*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?M(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,e=this.endPoint-this.startPoint;for(this.calculateYRange(e),this.buildYLabels(),this.calculateXLabelRotation();e>this.endPoint-this.startPoint;)e=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(e),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()},calculateXLabelRotation:function(){this.ctx.font=this.font;var t,e,i=this.ctx.measureText(this.xLabels[0]).width,n=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=n/2+3,this.xScalePaddingLeft=i/2>this.yLabelWidth+10?i/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var s,o=M(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)s=Math.cos(C(this.xLabelRotation)),t=s*i,e=s*n,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=s*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(C(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var e=this.drawingArea()/(this.min-this.max);return this.endPoint-e*(t-this.min)},calculateX:function(t){var e=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),i=e/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),n=i*t+this.xScalePaddingLeft;return this.offsetGridLines&&(n+=i/2),Math.round(n)},update:function(t){n.extend(this,t),this.fit()},draw:function(){var t=this.ctx,e=(this.endPoint-this.startPoint)/this.steps,i=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,s(this.yLabels,function(s,o){var a=this.endPoint-e*o,r=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(s,i-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),r+=n.aliasPixel(t.lineWidth),l&&(t.moveTo(i,r),t.lineTo(this.width,r),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(i-5,r),t.lineTo(i,r),t.stroke(),t.closePath()},this),s(this.xLabels,function(e,i){var n=this.calculateX(i)+y(this.lineWidth),s=this.calculateX(i-(this.offsetGridLines?.5:0))+y(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==i||a||(a=!0),a&&t.beginPath(),i>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(s,this.endPoint),t.lineTo(s,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(s,this.endPoint),t.lineTo(s,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(n,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*C(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(e,0,0),t.restore()},this))}}),i.RadialScale=i.Element.extend({initialize:function(){this.size=v([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var e=this.drawingArea/(this.max-this.min);return(t-this.min)*e},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=m(this.stepValue),e=0;e<=this.steps;e++)this.yLabels.push(w(this.templateString,{value:(this.min+e*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,e,i,n,s,o,a,r,l,h,c,u,d=v([this.height/2-this.pointLabelFontSize-5,this.width/2]),f=this.width,g=0;for(this.ctx.font=D(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),e=0;e<this.valuesCount;e++)t=this.getPointPosition(e,d),i=this.ctx.measureText(w(this.templateString,{value:this.labels[e]})).width+5,0===e||e===this.valuesCount/2?(n=i/2,t.x+n>f&&(f=t.x+n,s=e),t.x-n<g&&(g=t.x-n,a=e)):e<this.valuesCount/2?t.x+i>f&&(f=t.x+i,s=e):e>this.valuesCount/2&&t.x-i<g&&(g=t.x-i,a=e);l=g,h=Math.ceil(f-this.width),o=this.getIndexAngle(s),r=this.getIndexAngle(a),c=h/Math.sin(o+Math.PI/2),u=l/Math.sin(r+Math.PI/2),c=p(c)?c:0,u=p(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,e){var i=this.width-e-this.drawingArea,n=t+this.drawingArea;this.xCenter=(n+i)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var e=2*Math.PI/this.valuesCount;return t*e-Math.PI/2},getPointPosition:function(t,e){var i=this.getIndexAngle(t);return{x:Math.cos(i)*e+this.xCenter,y:Math.sin(i)*e+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(s(this.yLabels,function(e,i){if(i>0){var n,s=i*(this.drawingArea/this.steps),o=this.yCenter-s;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,s,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)n=this.getPointPosition(a,this.calculateCenterOffset(this.min+i*this.stepValue)),0===a?t.moveTo(n.x,n.y):t.lineTo(n.x,n.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=D(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var r=t.measureText(e).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-r/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,r+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(e,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var e=this.valuesCount-1;e>=0;e--){if(this.angleLineWidth>0){var i=this.getPointPosition(e,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(i.x,i.y),t.stroke(),t.closePath()}var n=this.getPointPosition(e,this.calculateCenterOffset(this.max)+5);t.font=D(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,r=a/2,l=r>e||e>o-r,h=e===r||e===o-r;0===e?t.textAlign="center":e===a?t.textAlign="center":a>e?t.textAlign="left":t.textAlign="right",h?t.textBaseline="middle":l?t.textBaseline="bottom":t.textBaseline="top",t.fillText(this.labels[e],n.x,n.y)}}}}}),n.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){s(i.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),f?define(function(){return i}):"object"==typeof module&&module.exports&&(module.exports=i),t.Chart=i,i.noConflict=function(){return t.Chart=e,i}}).call(this),function(){"use strict";var t=this,e=t.Chart,i=e.helpers,n={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};e.Type.extend({name:"Bar",defaults:n,initialize:function(t){var n=this.options;this.ScaleClass=e.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,e,i){var s=this.calculateBaseWidth(),o=this.calculateX(i)-s/2,a=this.calculateBarWidth(t);return o+a*e+e*n.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*n.barValueSpacing},calculateBarWidth:function(t){var e=this.calculateBaseWidth()-(t-1)*n.barDatasetSpacing;return e/t}}),this.datasets=[],this.options.showTooltips&&i.bindEvents(this,this.options.tooltipEvents,function(t){var e="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),i.each(e,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(e)}),this.BarClass=e.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),i.each(t.datasets,function(e,n){var s={label:e.label||null,fillColor:e.fillColor,strokeColor:e.strokeColor,bars:[]};this.datasets.push(s),i.each(e.data,function(i,n){s.bars.push(new this.BarClass({value:i,label:t.labels[n],datasetLabel:e.label,strokeColor:e.strokeColor,fillColor:e.fillColor,highlightFill:e.highlightFill||e.fillColor,highlightStroke:e.highlightStroke||e.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,e,n){i.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,n,e),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),i.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){i.each(this.datasets,function(e,n){i.each(e.bars,t,this,n)},this)},getBarsAtEvent:function(t){for(var e,n=[],s=i.getRelativePosition(t),o=function(t){n.push(t.bars[e])},a=0;a<this.datasets.length;a++)for(e=0;e<this.datasets[a].bars.length;e++)if(this.datasets[a].bars[e].inRange(s.x,s.y))return i.each(this.datasets,o),n;return n},buildScale:function(t){var e=this,n=function(){var t=[];return e.eachBars(function(e){t.push(e.value)}),t},s={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var e=i.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);i.extend(this,e)},xLabels:t,font:i.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&i.extend(s,{calculateYRange:i.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(s)},addData:function(t,e){i.each(t,function(t,i){this.datasets[i].bars.push(new this.BarClass({value:t,label:e,x:this.scale.calculateBarX(this.datasets.length,i,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),
+base:this.scale.endPoint,strokeColor:this.datasets[i].strokeColor,fillColor:this.datasets[i].fillColor}))},this),this.scale.addXLabel(e),this.update()},removeData:function(){this.scale.removeXLabel(),i.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){i.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=i.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var e=t||1;this.clear();this.chart.ctx;this.scale.draw(e),i.each(this.datasets,function(t,n){i.each(t.bars,function(t,i){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,n,i),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},e).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,e=t.Chart,i=e.helpers,n={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};e.Type.extend({name:"Doughnut",defaults:n,initialize:function(t){this.segments=[],this.outerRadius=(i.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=e.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&i.bindEvents(this,this.options.tooltipEvents,function(t){var e="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];i.each(this.segments,function(t){t.restore(["fillColor"])}),i.each(e,function(t){t.fillColor=t.highlightColor}),this.showTooltip(e)}),this.calculateTotal(t),i.each(t,function(t,e){this.addData(t,e,!0)},this),this.render()},getSegmentsAtEvent:function(t){var e=[],n=i.getRelativePosition(t);return i.each(this.segments,function(t){t.inRange(n.x,n.y)&&e.push(t)},this),e},addData:function(t,e,i){var n=e||this.segments.length;this.segments.splice(n,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),i||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,i.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),i.each(this.activeElements,function(t){t.restore(["fillColor"])}),i.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var e=i.isNumber(t)?t:this.segments.length-1;this.segments.splice(e,1),this.reflow(),this.update()},reflow:function(){i.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(i.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,i.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var e=t?t:1;this.clear(),i.each(this.segments,function(t,i){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},e),t.endAngle=t.startAngle+t.circumference,t.draw(),0===i&&(t.startAngle=1.5*Math.PI),i<this.segments.length-1&&(this.segments[i+1].startAngle=t.endAngle)},this)}}),e.types.Doughnut.extend({name:"Pie",defaults:i.merge(n,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,e=t.Chart,i=e.helpers,n={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};e.Type.extend({name:"Line",defaults:n,initialize:function(t){this.PointClass=e.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&i.bindEvents(this,this.options.tooltipEvents,function(t){var e="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),i.each(e,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(e)}),i.each(t.datasets,function(e){var n={label:e.label||null,fillColor:e.fillColor,strokeColor:e.strokeColor,pointColor:e.pointColor,pointStrokeColor:e.pointStrokeColor,points:[]};this.datasets.push(n),i.each(e.data,function(i,s){n.points.push(new this.PointClass({value:i,label:t.labels[s],datasetLabel:e.label,strokeColor:e.pointStrokeColor,fillColor:e.pointColor,highlightFill:e.pointHighlightFill||e.pointColor,highlightStroke:e.pointHighlightStroke||e.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,e){i.extend(t,{x:this.scale.calculateX(e),y:this.scale.endPoint}),t.save()},this)},this),this.render()},update:function(){this.scale.update(),i.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){i.each(this.datasets,function(e){i.each(e.points,t,this)},this)},getPointsAtEvent:function(t){var e=[],n=i.getRelativePosition(t);return i.each(this.datasets,function(t){i.each(t.points,function(t){t.inRange(n.x,n.y)&&e.push(t)})},this),e},buildScale:function(t){var n=this,s=function(){var t=[];return n.eachPoints(function(e){t.push(e.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var e=i.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);i.extend(this,e)},xLabels:t,font:i.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,showHorizontalLines:this.options.scaleShowHorizontalLines,showVerticalLines:this.options.scaleShowVerticalLines,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&i.extend(o,{calculateYRange:i.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new e.Scale(o)},addData:function(t,e){i.each(t,function(t,i){this.datasets[i].points.push(new this.PointClass({value:t,label:e,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[i].pointStrokeColor,fillColor:this.datasets[i].pointColor}))},this),this.scale.addXLabel(e),this.update()},removeData:function(){this.scale.removeXLabel(),i.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=i.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var e=t||1;this.clear();var n=this.chart.ctx,s=function(t){return null!==t.value},o=function(t,e,n){return i.findNextWhere(e,s,n)||t},a=function(t,e,n){return i.findPreviousWhere(e,s,n)||t};this.scale.draw(e),i.each(this.datasets,function(t){var r=i.where(t.points,s);i.each(t.points,function(t,i){t.hasValue()&&t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(i)},e)},this),this.options.bezierCurve&&i.each(r,function(t,e){var n=e>0&&e<r.length-1?this.options.bezierCurveTension:0;t.controlPoints=i.splineCurve(a(t,r,e),t,o(t,r,e),n),t.controlPoints.outer.y>this.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.y<this.scale.startPoint&&(t.controlPoints.outer.y=this.scale.startPoint),t.controlPoints.inner.y>this.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y<this.scale.startPoint&&(t.controlPoints.inner.y=this.scale.startPoint)},this),n.lineWidth=this.options.datasetStrokeWidth,n.strokeStyle=t.strokeColor,n.beginPath(),i.each(r,function(t,e){if(0===e)n.moveTo(t.x,t.y);else if(this.options.bezierCurve){var i=a(t,r,e);n.bezierCurveTo(i.controlPoints.outer.x,i.controlPoints.outer.y,t.controlPoints.inner.x,t.controlPoints.inner.y,t.x,t.y)}else n.lineTo(t.x,t.y)},this),n.stroke(),this.options.datasetFill&&r.length>0&&(n.lineTo(r[r.length-1].x,this.scale.endPoint),n.lineTo(r[0].x,this.scale.endPoint),n.fillStyle=t.fillColor,n.closePath(),n.fill()),i.each(r,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,e=t.Chart,i=e.helpers,n={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};e.Type.extend({name:"PolarArea",defaults:n,initialize:function(t){this.segments=[],this.SegmentArc=e.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new e.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),i.each(t,function(t,e){this.addData(t,e,!0)},this),this.options.showTooltips&&i.bindEvents(this,this.options.tooltipEvents,function(t){var e="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];i.each(this.segments,function(t){t.restore(["fillColor"])}),i.each(e,function(t){t.fillColor=t.highlightColor}),this.showTooltip(e)}),this.render()},getSegmentsAtEvent:function(t){var e=[],n=i.getRelativePosition(t);return i.each(this.segments,function(t){t.inRange(n.x,n.y)&&e.push(t)},this),e},addData:function(t,e,i){var n=e||this.segments.length;this.segments.splice(n,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),i||(this.reflow(),this.update())},removeData:function(t){var e=i.isNumber(t)?t:this.segments.length-1;this.segments.splice(e,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,i.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var e=[];i.each(t,function(t){e.push(t.value)});var n=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:i.calculateScaleRange(e,i.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);i.extend(this.scale,n,{size:i.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),i.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){i.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),i.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),i.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var e=t||1;this.clear(),i.each(this.segments,function(t,i){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},e),t.endAngle=t.startAngle+t.circumference,0===i&&(t.startAngle=1.5*Math.PI),i<this.segments.length-1&&(this.segments[i+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,e=t.Chart,i=e.helpers;e.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=e.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&i.bindEvents(this,this.options.tooltipEvents,function(t){var e="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),i.each(e,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(e)}),i.each(t.datasets,function(e){var n={label:e.label||null,fillColor:e.fillColor,strokeColor:e.strokeColor,pointColor:e.pointColor,pointStrokeColor:e.pointStrokeColor,points:[]};this.datasets.push(n),i.each(e.data,function(i,s){var o;this.scale.animation||(o=this.scale.getPointPosition(s,this.scale.calculateCenterOffset(i))),n.points.push(new this.PointClass({value:i,label:t.labels[s],datasetLabel:e.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:e.pointStrokeColor,fillColor:e.pointColor,highlightFill:e.pointHighlightFill||e.pointColor,highlightStroke:e.pointHighlightStroke||e.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){i.each(this.datasets,function(e){i.each(e.points,t,this)},this)},getPointsAtEvent:function(t){var e=i.getRelativePosition(t),n=i.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},e),s=2*Math.PI/this.scale.valuesCount,o=Math.round((n.angle-1.5*Math.PI)/s),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),n.distance<=this.scale.drawingArea&&i.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new e.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var e=function(){var e=[];return i.each(t,function(t){t.data?e=e.concat(t.data):i.each(t.points,function(t){e.push(t.value)})}),e}(),n=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:i.calculateScaleRange(e,i.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);i.extend(this.scale,n)},addData:function(t,e){this.scale.valuesCount++,i.each(t,function(t,i){var n=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[i].points.push(new this.PointClass({value:t,label:e,x:n.x,y:n.y,strokeColor:this.datasets[i].pointStrokeColor,fillColor:this.datasets[i].pointColor}))},this),this.scale.labels.push(e),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),i.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){i.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:i.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var e=t||1,n=this.chart.ctx;this.clear(),this.scale.draw(),i.each(this.datasets,function(t){i.each(t.points,function(t,i){t.hasValue()&&t.transition(this.scale.getPointPosition(i,this.scale.calculateCenterOffset(t.value)),e)},this),n.lineWidth=this.options.datasetStrokeWidth,n.strokeStyle=t.strokeColor,n.beginPath(),i.each(t.points,function(t,e){0===e?n.moveTo(t.x,t.y):n.lineTo(t.x,t.y)},this),n.closePath(),n.stroke(),n.fillStyle=t.fillColor,n.fill(),i.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this),function(t){"use strict";"object"==typeof exports?module.exports=t(angular,Chart):"function"==typeof define&&define.amd?define(["angular","chart"],t):t(angular,Chart)}(function(t,e){"use strict";function i(){var i={},n={Chart:e,getOptions:function(e){var n=e&&i[e]||{};return t.extend({},i,n)}};this.setOptions=function(e,n){return n?void(i[e]=t.extend(i[e]||{},n)):(n=e,void(i=t.extend(i,n)))},this.$get=function(){return n}}function n(i,n){function o(t,e){return t&&e&&t.length&&e.length?Array.isArray(t[0])?t.length===e.length&&t.every(function(t,i){return t.length===e[i].length}):e.reduce(a,0)>0?t.length===e.length:!1:!1}function a(t,e){return t+e}function r(e,i,n,s){var o=null;return function(a){var r=i.getPointsAtEvent||i.getBarsAtEvent||i.getSegmentsAtEvent;if(r){var l=r.call(i,a);(s===!1||t.equals(o,l)===!1)&&(o=l,e[n](l,a),e.$apply())}}}function l(n,s){for(var o=t.copy(s.colours||i.getOptions(n).colours||e.defaults.global.colours);o.length<s.data.length;)o.push(s.getColour());return o.map(h)}function h(t){return"object"==typeof t&&null!==t?t:"string"==typeof t&&"#"===t[0]?u(p(t.substr(1))):c()}function c(){var t=[d(0,255),d(0,255),d(0,255)];return u(t)}function u(t){return{fillColor:f(t,.2),strokeColor:f(t,1),pointColor:f(t,1),pointStrokeColor:"#fff",pointHighlightFill:"#fff",pointHighlightStroke:f(t,.8)}}function d(t,e){return Math.floor(Math.random()*(e-t+1))+t}function f(t,e){return s?"rgb("+t.join(",")+")":"rgba("+t.concat(e).join(",")+")"}function p(t){var e=parseInt(t,16),i=e>>16&255,n=e>>8&255,s=255&e;return[i,n,s]}function g(e,i,n,s){return{labels:e,datasets:i.map(function(e,i){return t.extend({},s[i],{label:n[i],data:e})})}}function v(e,i,n){return e.map(function(e,s){return t.extend({},n[s],{label:e,value:i[s],color:n[s].strokeColor,highlight:n[s].pointHighlightStroke})})}function m(t,e){var i=t.parent(),n=i.find("chart-legend"),s="<chart-legend>"+e.generateLegend()+"</chart-legend>";n.length?n.replaceWith(s):i.append(s)}function C(t,e,i,n){Array.isArray(i.data[0])?t.datasets.forEach(function(t,i){(t.points||t.bars).forEach(function(t,n){t.value=e[i][n]})}):t.segments.forEach(function(t,i){t.value=e[i]}),t.update(),i.$emit("update",t),i.legend&&"false"!==i.legend&&m(n,t)}function y(t){return!t||Array.isArray(t)&&!t.length||"object"==typeof t&&!Object.keys(t).length}function b(n,s){var o=t.extend({},e.defaults.global,i.getOptions(n),s.options);return o.responsive}return function(e){return{restrict:"CA",scope:{data:"=?",labels:"=?",options:"=?",series:"=?",colours:"=?",getColour:"=?",chartType:"=",legend:"@",click:"=?",hover:"=?",chartData:"=?",chartLabels:"=?",chartOptions:"=?",chartSeries:"=?",chartColours:"=?",chartLegend:"@",chartClick:"=?",chartHover:"=?"},link:function(a,h){function u(t,e){a.$watch(t,function(t){"undefined"!=typeof t&&(a[e]=t)})}function d(i,n){if(!y(i)&&!t.equals(i,n)){var s=e||a.chartType;s&&(w&&w.destroy(),f(s))}}function f(e){if(b(e,a)&&0===h[0].clientHeight&&0===x.clientHeight)return n(function(){f(e)},50,!1);if(a.data&&a.data.length){a.getColour="function"==typeof a.getColour?a.getColour:c,a.colours=l(e,a);var s=h[0],o=s.getContext("2d"),u=Array.isArray(a.data[0])?g(a.labels,a.data,a.series||[],a.colours):v(a.labels,a.data,a.colours),d=t.extend({},i.getOptions(e),a.options);w=new i.Chart(o)[e](u,d),a.$emit("create",w),s.onclick=a.click?r(a,w,"click",!1):t.noop,s.onmousemove=a.hover?r(a,w,"hover",!0):t.noop,a.legend&&"false"!==a.legend&&m(h,w)}}function p(t){if("undefined"!=typeof console&&"test"!==i.getOptions().env){var e="function"==typeof console.warn?console.warn:console.log;a[t]&&e.call(console,'"%s" is deprecated and will be removed in a future version. Please use "chart-%s" instead.',t,t)}}var w,x=document.createElement("div");x.className="chart-container",h.replaceWith(x),x.appendChild(h[0]),s&&window.G_vmlCanvasManager.initElement(h[0]),["data","labels","options","series","colours","legend","click","hover"].forEach(p),u("chartData","data"),u("chartLabels","labels"),u("chartOptions","options"),u("chartSeries","series"),u("chartColours","colours"),u("chartLegend","legend"),u("chartClick","click"),u("chartHover","hover"),a.$watch("data",function(t,i){if(t&&t.length&&(!Array.isArray(t[0])||t[0].length)){var n=e||a.chartType;if(n){if(w){if(o(t,i))return C(w,t,a,h);w.destroy()}f(n)}}},!0),a.$watch("series",d,!0),a.$watch("labels",d,!0),a.$watch("options",d,!0),a.$watch("colours",d,!0),a.$watch("chartType",function(e,i){y(e)||t.equals(e,i)||(w&&w.destroy(),f(e))}),a.$on("$destroy",function(){w&&w.destroy()})}}}}e.defaults.global.responsive=!0,e.defaults.global.multiTooltipTemplate="<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>",e.defaults.global.colours=["#97BBCD","#DCDCDC","#F7464A","#46BFBD","#FDB45C","#949FB1","#4D5360"];var s="object"==typeof window.G_vmlCanvasManager&&null!==window.G_vmlCanvasManager&&"function"==typeof window.G_vmlCanvasManager.initElement;return s&&(e.defaults.global.animation=!1),t.module("chart.js",[]).provider("ChartJs",i).factory("ChartJsFactory",["ChartJs","$timeout",n]).directive("chartBase",["ChartJsFactory",function(t){return new t}]).directive("chartLine",["ChartJsFactory",function(t){return new t("Line")}]).directive("chartBar",["ChartJsFactory",function(t){return new t("Bar")}]).directive("chartRadar",["ChartJsFactory",function(t){return new t("Radar")}]).directive("chartDoughnut",["ChartJsFactory",function(t){return new t("Doughnut")}]).directive("chartPie",["ChartJsFactory",function(t){return new t("Pie")}]).directive("chartPolarArea",["ChartJsFactory",function(t){return new t("PolarArea")}])}),function(t,e,i){"use strict";function n(t,e,i){if(!t)throw ngMinErr("areq","Argument '{0}' is {1}",e||"?",i||"required");return t}function s(t,e){return t||e?t?e?(q(t)&&(t=t.join(" ")),q(e)&&(e=e.join(" ")),t+" "+e):t:e:""}function o(t){var e={};return t&&(t.to||t.from)&&(e.to=t.to,e.from=t.from),e}function a(t,e,i){var n="";return t=q(t)?t:t&&X(t)&&t.length?t.split(/\s+/):[],j(t,function(t,s){t&&t.length>0&&(n+=s>0?" ":"",n+=i?e+t:t+e)}),n}function r(t,e){var i=t.indexOf(e);e>=0&&t.splice(i,1)}function l(t){if(t instanceof H)switch(t.length){case 0:return[];case 1:if(t[0].nodeType===U)return t;break;default:return H(h(t))}return t.nodeType===U?H(t):void 0}function h(t){if(!t[0])return t;for(var e=0;e<t.length;e++){var i=t[e];if(i.nodeType==U)return i}}function c(t,e,i){j(e,function(e){t.addClass(e,i)})}function u(t,e,i){j(e,function(e){t.removeClass(e,i)})}function d(t){return function(e,i){i.addClass&&(c(t,e,i.addClass),i.addClass=null),i.removeClass&&(u(t,e,i.removeClass),i.removeClass=null)}}function f(t){if(t=t||{},!t.$$prepared){var e=t.domOperation||B;t.domOperation=function(){t.$$domOperationFired=!0,e(),e=B},t.$$prepared=!0}return t}function p(t,e){g(t,e),v(t,e)}function g(t,e){e.from&&(t.css(e.from),e.from=null)}function v(t,e){e.to&&(t.css(e.to),e.to=null)}function m(t,e,i){var n=(e.addClass||"")+" "+(i.addClass||""),s=(e.removeClass||"")+" "+(i.removeClass||""),o=C(t.attr("class"),n,s);i.preparationClasses&&(e.preparationClasses=k(i.preparationClasses,e.preparationClasses),delete i.preparationClasses);var a=e.domOperation!==B?e.domOperation:null;return I(e,i),a&&(e.domOperation=a),o.addClass?e.addClass=o.addClass:e.addClass=null,o.removeClass?e.removeClass=o.removeClass:e.removeClass=null,e}function C(t,e,i){function n(t){X(t)&&(t=t.split(" "));var e={};return j(t,function(t){t.length&&(e[t]=!0)}),e}var s=1,o=-1,a={};t=n(t),e=n(e),j(e,function(t,e){a[e]=s}),i=n(i),j(i,function(t,e){a[e]=a[e]===s?null:o});var r={addClass:"",removeClass:""};return j(a,function(e,i){var n,a;e===s?(n="addClass",a=!t[i]):e===o&&(n="removeClass",a=t[i]),a&&(r[n].length&&(r[n]+=" "),r[n]+=i)}),r}function y(t){return t instanceof e.element?t[0]:t}function b(t,e,i){var n="";e&&(n=a(e,Z,!0)),i.addClass&&(n=k(n,a(i.addClass,J))),i.removeClass&&(n=k(n,a(i.removeClass,Q))),n.length&&(i.preparationClasses=n,t.addClass(n))}function w(t,e){e.preparationClasses&&(t.removeClass(e.preparationClasses),e.preparationClasses=null),e.activeClasses&&(t.removeClass(e.activeClasses),e.activeClasses=null)}function x(t,e){var i=e?"-"+e+"s":"";return P(t,[dt,i]),[dt,i]}function S(t,e){var i=e?"paused":"",n=z+lt;return P(t,[n,i]),[n,i]}function P(t,e){var i=e[0],n=e[1];t.style[i]=n}function k(t,e){return t?e?t+" "+e:t:e}function A(t){return[ut,t+"s"]}function L(t,e){var i=e?ct:dt;return[i,t+"s"]}function $(t,e,i){var n=Object.create(null),s=t.getComputedStyle(e)||{};return j(i,function(t,e){var i=s[t];if(i){var o=i.charAt(0);("-"===o||"+"===o||o>=0)&&(i=F(i)),0===i&&(i=null),n[e]=i}}),n}function F(t){var e=0,i=t.split(/\s*,\s*/);return j(i,function(t){"s"==t.charAt(t.length-1)&&(t=t.substring(0,t.length-1)),t=parseFloat(t)||0,e=e?Math.max(t,e):t}),e}function T(t){return 0===t||null!=t}function R(t,e){var i=W,n=t+"s";return e?i+=nt:n+=" linear all",[i,n]}function D(){var t=Object.create(null);return{flush:function(){t=Object.create(null)},count:function(e){var i=t[e];return i?i.total:0},get:function(e){var i=t[e];return i&&i.value},put:function(e,i){t[e]?t[e].total++:t[e]={total:1,value:i}}}}function M(t,e,i){j(i,function(i){t[i]=_(t[i])?t[i]:e.style.getPropertyValue(i)})}var W,O,z,E,B=e.noop,I=e.extend,H=e.element,j=e.forEach,q=e.isArray,X=e.isString,V=e.isObject,G=e.isUndefined,_=e.isDefined,N=e.isFunction,Y=e.isElement,U=1,J="-add",Q="-remove",Z="ng-",K="-active",tt="ng-animate",et="$$ngAnimateChildren",it="";G(t.ontransitionend)&&_(t.onwebkittransitionend)?(it="-webkit-",W="WebkitTransition",O="webkitTransitionEnd transitionend"):(W="transition",O="transitionend"),G(t.onanimationend)&&_(t.onwebkitanimationend)?(it="-webkit-",z="WebkitAnimation",E="webkitAnimationEnd animationend"):(z="animation",E="animationend");var nt="Duration",st="Property",ot="Delay",at="TimingFunction",rt="IterationCount",lt="PlayState",ht=9999,ct=z+ot,ut=z+nt,dt=W+ot,ft=W+nt,pt=["$$rAF",function(t){function e(t){n=n.concat(t),i()}function i(){if(n.length){for(var e=n.shift(),o=0;o<e.length;o++)e[o]();s||t(function(){s||i()})}}var n,s;return n=e.queue=[],e.waitUntilQuiet=function(e){s&&s(),s=t(function(){s=null,e(),i()})},e}],gt=[function(){return function(t,i,n){var s=n.ngAnimateChildren;e.isString(s)&&0===s.length?i.data(et,!0):n.$observe("ngAnimateChildren",function(t){t="on"===t||"true"===t,i.data(et,t)})}}],vt="$$animateCss",mt=1e3,Ct=3,yt=1.5,bt={transitionDuration:ft,transitionDelay:dt,transitionProperty:W+st,animationDuration:ut,animationDelay:ct,animationIterationCount:z+rt},wt={transitionDuration:ft,transitionDelay:dt,animationDuration:ut,animationDelay:ct},xt=["$animateProvider",function(t){var e=D(),i=D();this.$get=["$window","$$jqLite","$$AnimateRunner","$timeout","$$forceReflow","$sniffer","$$rAFScheduler","$animate",function(t,n,s,l,h,c,u,m){function C(t,e){var i="$$ngAnimateParentKey",n=t.parentNode,s=n[i]||(n[i]=++I);return s+"-"+t.getAttribute("class")+"-"+e}function b(i,n,s,o){var a=e.get(s);return a||(a=$(t,i,o),"infinite"===a.animationIterationCount&&(a.animationIterationCount=1)),e.put(s,a),a}function w(s,o,r,l){var h;if(e.count(r)>0&&(h=i.get(r),!h)){var c=a(o,"-stagger");n.addClass(s,c),h=$(t,s,l),h.animationDuration=Math.max(h.animationDuration,0),h.transitionDuration=Math.max(h.transitionDuration,0),n.removeClass(s,c),i.put(r,h)}return h||{}}function k(t){H.push(t),u.waitUntilQuiet(function(){e.flush(),i.flush();for(var t=h(),n=0;n<H.length;n++)H[n](t);H.length=0})}function F(t,e,i){var n=b(t,e,i,bt),s=n.animationDelay,o=n.transitionDelay;return n.maxDelay=s&&o?Math.max(s,o):s||o,n.maxDuration=Math.max(n.animationDuration*n.animationIterationCount,n.transitionDuration),n}var D=d(n),I=0,H=[];return function(t,i){function h(){d()}function u(){d(!0)}function d(e){V||_&&G||(V=!0,G=!1,i.$$skipPreparationClasses||n.removeClass(t,ft),n.removeClass(t,gt),S(X,!1),x(X,!1),j(nt,function(t){X.style[t[0]]=""}),D(t,i),p(t,i),Object.keys(H).length&&j(H,function(t,e){t?X.style.setProperty(e,t):X.style.removeProperty(e)}),i.onDone&&i.onDone(),N&&N.complete(!e));
+}function b(t){Wt.blockTransition&&x(X,t),Wt.blockKeyframeAnimation&&S(X,!!t)}function $(){return N=new s({end:h,cancel:u}),k(B),d(),{$$willAnimate:!1,start:function(){return N},end:h}}function I(){function e(){if(!V){if(b(!1),j(nt,function(t){var e=t[0],i=t[1];X.style[e]=i}),D(t,i),n.addClass(t,gt),Wt.recalculateTimingStyles){if(pt=X.className+" "+ft,St=C(X,pt),Dt=F(X,pt,St),Mt=Dt.maxDelay,U=Math.max(Mt,0),et=Dt.maxDuration,0===et)return void d();Wt.hasTransitions=Dt.transitionDuration>0,Wt.hasAnimations=Dt.animationDuration>0}if(Wt.applyAnimationDelay&&(Mt="boolean"!=typeof i.delay&&T(i.delay)?parseFloat(i.delay):Mt,U=Math.max(Mt,0),Dt.animationDelay=Mt,Ot=L(Mt,!0),nt.push(Ot),X.style[Ot[0]]=Ot[1]),tt=U*mt,it=et*mt,i.easing){var e,r=i.easing;Wt.hasTransitions&&(e=W+at,nt.push([e,r]),X.style[e]=r),Wt.hasAnimations&&(e=z+at,nt.push([e,r]),X.style[e]=r)}Dt.transitionDuration&&h.push(O),Dt.animationDuration&&h.push(E),a=Date.now();var c=tt+yt*it,u=a+c,f=t.data(vt)||[],p=!0;if(f.length){var g=f[0];p=u>g.expectedEndTime,p?l.cancel(g.timer):f.push(d)}if(p){var m=l(s,c,!1);f[0]={timer:m,expectedEndTime:u},f.push(d),t.data(vt,f)}t.on(h.join(" "),o),i.to&&(i.cleanupStyles&&M(H,X,Object.keys(i.to)),v(t,i))}}function s(){var e=t.data(vt);if(e){for(var i=1;i<e.length;i++)e[i]();t.removeData(vt)}}function o(t){t.stopPropagation();var e=t.originalEvent||t,i=e.$manualTimeStamp||e.timeStamp||Date.now(),n=parseFloat(e.elapsedTime.toFixed(Ct));Math.max(i-a,0)>=tt&&n>=et&&(_=!0,d())}if(!V){if(!X.parentNode)return void d();var a,h=[],c=function(t){if(_)G&&t&&(G=!1,d());else if(G=!t,Dt.animationDuration){var e=S(X,G);G?nt.push(e):r(nt,e)}},u=Tt>0&&(Dt.transitionDuration&&0===Pt.transitionDuration||Dt.animationDuration&&0===Pt.animationDuration)&&Math.max(Pt.animationDelay,Pt.transitionDelay);u?l(e,Math.floor(u*Tt*mt),!1):e(),Y.resume=function(){c(!0)},Y.pause=function(){c(!1)}}}var H={},X=y(t);if(!X||!X.parentNode||!m.enabled())return $();i=f(i);var V,G,_,N,Y,U,tt,et,it,nt=[],ot=t.attr("class"),rt=o(i);if(0===i.duration||!c.animations&&!c.transitions)return $();var lt=i.event&&q(i.event)?i.event.join(" "):i.event,ct=lt&&i.structural,ut="",dt="";ct?ut=a(lt,Z,!0):lt&&(ut=lt),i.addClass&&(dt+=a(i.addClass,J)),i.removeClass&&(dt.length&&(dt+=" "),dt+=a(i.removeClass,Q)),i.applyClassesEarly&&dt.length&&D(t,i);var ft=[ut,dt].join(" ").trim(),pt=ot+" "+ft,gt=a(ft,K),bt=rt.to&&Object.keys(rt.to).length>0,xt=(i.keyframeStyle||"").length>0;if(!xt&&!bt&&!ft)return $();var St,Pt;if(i.stagger>0){var kt=parseFloat(i.stagger);Pt={transitionDelay:kt,animationDelay:kt,transitionDuration:0,animationDuration:0}}else St=C(X,pt),Pt=w(X,ft,St,wt);i.$$skipPreparationClasses||n.addClass(t,ft);var At;if(i.transitionStyle){var Lt=[W,i.transitionStyle];P(X,Lt),nt.push(Lt)}if(i.duration>=0){At=X.style[W].length>0;var $t=R(i.duration,At);P(X,$t),nt.push($t)}if(i.keyframeStyle){var Ft=[z,i.keyframeStyle];P(X,Ft),nt.push(Ft)}var Tt=Pt?i.staggerIndex>=0?i.staggerIndex:e.count(St):0,Rt=0===Tt;Rt&&!i.skipBlocking&&x(X,ht);var Dt=F(X,pt,St),Mt=Dt.maxDelay;U=Math.max(Mt,0),et=Dt.maxDuration;var Wt={};if(Wt.hasTransitions=Dt.transitionDuration>0,Wt.hasAnimations=Dt.animationDuration>0,Wt.hasTransitionAll=Wt.hasTransitions&&"all"==Dt.transitionProperty,Wt.applyTransitionDuration=bt&&(Wt.hasTransitions&&!Wt.hasTransitionAll||Wt.hasAnimations&&!Wt.hasTransitions),Wt.applyAnimationDuration=i.duration&&Wt.hasAnimations,Wt.applyTransitionDelay=T(i.delay)&&(Wt.applyTransitionDuration||Wt.hasTransitions),Wt.applyAnimationDelay=T(i.delay)&&Wt.hasAnimations,Wt.recalculateTimingStyles=dt.length>0,(Wt.applyTransitionDuration||Wt.applyAnimationDuration)&&(et=i.duration?parseFloat(i.duration):et,Wt.applyTransitionDuration&&(Wt.hasTransitions=!0,Dt.transitionDuration=et,At=X.style[W+st].length>0,nt.push(R(et,At))),Wt.applyAnimationDuration&&(Wt.hasAnimations=!0,Dt.animationDuration=et,nt.push(A(et)))),0===et&&!Wt.recalculateTimingStyles)return $();if(null!=i.delay){var Ot=parseFloat(i.delay);Wt.applyTransitionDelay&&nt.push(L(Ot)),Wt.applyAnimationDelay&&nt.push(L(Ot,!0))}return null==i.duration&&Dt.transitionDuration>0&&(Wt.recalculateTimingStyles=Wt.recalculateTimingStyles||Rt),tt=U*mt,it=et*mt,i.skipBlocking||(Wt.blockTransition=Dt.transitionDuration>0,Wt.blockKeyframeAnimation=Dt.animationDuration>0&&Pt.animationDelay>0&&0===Pt.animationDuration),i.from&&(i.cleanupStyles&&M(H,X,Object.keys(i.from)),g(t,i)),Wt.blockTransition||Wt.blockKeyframeAnimation?b(et):i.skipBlocking||x(X,!1),{$$willAnimate:!0,end:h,start:function(){return V?void 0:(Y={end:h,cancel:u,resume:null,pause:null},N=new s(Y),k(I),N)}}}}]}],St=["$$animationProvider",function(t){function e(t){return t.parentNode&&11===t.parentNode.nodeType}t.drivers.push("$$animateCssDriver");var i="ng-animate-shim",n="ng-anchor",s="ng-anchor-out",o="ng-anchor-in";this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$sniffer","$$jqLite","$document",function(t,a,r,l,h,c,u){function f(t){return t.replace(/\bng-\S+\b/g,"")}function p(t,e){return X(t)&&(t=t.split(" ")),X(e)&&(e=e.split(" ")),t.filter(function(t){return-1===e.indexOf(t)}).join(" ")}function g(e,a,l){function h(t){var e={},i=y(t).getBoundingClientRect();return j(["width","height","top","left"],function(t){var n=i[t];switch(t){case"top":n+=C.scrollTop;break;case"left":n+=C.scrollLeft}e[t]=Math.floor(n)+"px"}),e}function c(){var e=t(v,{addClass:s,delay:!0,from:h(a)});return e.$$willAnimate?e:null}function u(t){return t.attr("class")||""}function d(){var e=f(u(l)),i=p(e,m),n=p(m,e),a=t(v,{to:h(l),addClass:o+" "+i,removeClass:s+" "+n,delay:!0});return a.$$willAnimate?a:null}function g(){v.remove(),a.removeClass(i),l.removeClass(i)}var v=H(y(a).cloneNode(!0)),m=f(u(v));a.addClass(i),l.addClass(i),v.addClass(n),w.append(v);var b,x=c();if(!x&&(b=d(),!b))return g();var S=x||b;return{start:function(){function t(){i&&i.end()}var e,i=S.start();return i.done(function(){return i=null,!b&&(b=d())?(i=b.start(),i.done(function(){i=null,g(),e.complete()}),i):(g(),void e.complete())}),e=new r({end:t,cancel:t})}}}function v(t,e,i,n){var s=m(t,B),o=m(e,B),a=[];return j(n,function(t){var e=t.out,n=t["in"],s=g(i,e,n);s&&a.push(s)}),s||o||0!==a.length?{start:function(){function t(){j(e,function(t){t.end()})}var e=[];s&&e.push(s.start()),o&&e.push(o.start()),j(a,function(t){e.push(t.start())});var i=new r({end:t,cancel:t});return r.all(e,function(t){i.complete(t)}),i}}:void 0}function m(e){var i=e.element,n=e.options||{};e.structural&&(n.event=e.event,n.structural=!0,n.applyClassesEarly=!0,"leave"===e.event&&(n.onDone=n.domOperation)),n.preparationClasses&&(n.event=k(n.event,n.preparationClasses));var s=t(i,n);return s.$$willAnimate?s:null}if(!h.animations&&!h.transitions)return B;var C=u[0].body,b=y(l),w=H(e(b)||C.contains(b)?b:C);d(c);return function(t){return t.from&&t.to?v(t.from,t.to,t.classes,t.anchors):m(t)}}]}],Pt=["$animateProvider",function(t){this.$get=["$injector","$$AnimateRunner","$$jqLite",function(e,i,n){function s(i){i=q(i)?i:i.split(" ");for(var n=[],s={},o=0;o<i.length;o++){var a=i[o],r=t.$$registeredAnimations[a];r&&!s[a]&&(n.push(e.get(r)),s[a]=!0)}return n}var o=d(n);return function(t,e,n,a){function r(){a.domOperation(),o(t,a)}function l(t,e,n,s,o){var a;switch(n){case"animate":a=[e,s.from,s.to,o];break;case"setClass":a=[e,g,v,o];break;case"addClass":a=[e,g,o];break;case"removeClass":a=[e,v,o];break;default:a=[e,o]}a.push(s);var r=t.apply(t,a);if(r)if(N(r.start)&&(r=r.start()),r instanceof i)r.done(o);else if(N(r))return r;return B}function h(t,e,n,s,o){var a=[];return j(s,function(s){var r=s[o];r&&a.push(function(){var s,o,a=!1,h=function(t){a||(a=!0,(o||B)(t),s.complete(!t))};return s=new i({end:function(){h()},cancel:function(){h(!0)}}),o=l(r,t,e,n,function(t){var e=t===!1;h(e)}),s})}),a}function c(t,e,n,s,o){var a=h(t,e,n,s,o);if(0===a.length){var r,l;"beforeSetClass"===o?(r=h(t,"removeClass",n,s,"beforeRemoveClass"),l=h(t,"addClass",n,s,"beforeAddClass")):"setClass"===o&&(r=h(t,"removeClass",n,s,"removeClass"),l=h(t,"addClass",n,s,"addClass")),r&&(a=a.concat(r)),l&&(a=a.concat(l))}if(0!==a.length)return function(t){var e=[];return a.length&&j(a,function(t){e.push(t())}),e.length?i.all(e,t):t(),function(t){j(e,function(e){t?e.cancel():e.end()})}}}3===arguments.length&&V(n)&&(a=n,n=null),a=f(a),n||(n=t.attr("class")||"",a.addClass&&(n+=" "+a.addClass),a.removeClass&&(n+=" "+a.removeClass));var u,d,g=a.addClass,v=a.removeClass,m=s(n);if(m.length){var C,y;"leave"==e?(y="leave",C="afterLeave"):(y="before"+e.charAt(0).toUpperCase()+e.substr(1),C=e),"enter"!==e&&"move"!==e&&(u=c(t,e,a,m,y)),d=c(t,e,a,m,C)}return u||d?{start:function(){function e(e){l=!0,r(),p(t,a),h.complete(e)}function n(t){l||((s||B)(t),e(t))}var s,o=[];u&&o.push(function(t){s=u(t)}),o.length?o.push(function(t){r(),t(!0)}):r(),d&&o.push(function(t){s=d(t)});var l=!1,h=new i({end:function(){n()},cancel:function(){n(!0)}});return i.chain(o,e),h}}:void 0}}]}],kt=["$$animationProvider",function(t){t.drivers.push("$$animateJsDriver"),this.$get=["$$animateJs","$$AnimateRunner",function(t,e){function i(e){var i=e.element,n=e.event,s=e.options,o=e.classes;return t(i,n,o,s)}return function(t){if(t.from&&t.to){var n=i(t.from),s=i(t.to);if(!n&&!s)return;return{start:function(){function t(){return function(){j(o,function(t){t.end()})}}function i(t){a.complete(t)}var o=[];n&&o.push(n.start()),s&&o.push(s.start()),e.all(o,i);var a=new e({end:t(),cancel:t()});return a}}}return i(t)}}]}],At="data-ng-animate",Lt="$ngAnimatePin",$t=["$animateProvider",function(t){function e(t,e,i,n){return a[t].some(function(t){return t(e,i,n)})}function i(t,e){t=t||{};var i=(t.addClass||"").length>0,n=(t.removeClass||"").length>0;return e?i&&n:i||n}var s=1,o=2,a=this.rules={skip:[],cancel:[],join:[]};a.join.push(function(t,e,n){return!e.structural&&i(e.options)}),a.skip.push(function(t,e,n){return!e.structural&&!i(e.options)}),a.skip.push(function(t,e,i){return"leave"==i.event&&e.structural}),a.skip.push(function(t,e,i){return i.structural&&i.state===o&&!e.structural}),a.cancel.push(function(t,e,i){return i.structural&&e.structural}),a.cancel.push(function(t,e,i){return i.state===o&&e.structural}),a.cancel.push(function(t,e,i){var n=e.options,s=i.options;return n.addClass&&n.addClass===s.removeClass||n.removeClass&&n.removeClass===s.addClass}),this.$get=["$$rAF","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite","$$forceReflow",function(a,r,c,u,g,v,C,x,S,P){function k(){var t=!1;return function(e){t?e():r.$$postDigest(function(){t=!0,e()})}}function A(t,e){return m(t,e,{})}function L(t,e,i){var n=y(e),s=y(t),o=[],a=B[i];return a&&j(a,function(t){t.node.contains(n)?o.push(t.callback):"leave"===i&&t.node.contains(s)&&o.push(t.callback)}),o}function $(t,n,h){function c(e,i,n,s){S(function(){var e=L(g,t,i);e.length&&a(function(){j(e,function(e){e(t,n,s)})})}),e.progress(i,n,s)}function u(e){w(t,h),Q(t,h),p(t,h),h.domOperation(),x.complete(!e)}var d,g;t=l(t),t&&(d=y(t),g=t.parent()),h=f(h);var x=new C,S=k();if(q(h.addClass)&&(h.addClass=h.addClass.join(" ")),h.addClass&&!X(h.addClass)&&(h.addClass=null),q(h.removeClass)&&(h.removeClass=h.removeClass.join(" ")),h.removeClass&&!X(h.removeClass)&&(h.removeClass=null),h.from&&!V(h.from)&&(h.from=null),h.to&&!V(h.to)&&(h.to=null),!d)return u(),x;var P=[d.className,h.addClass,h.removeClass].join(" ");if(!J(P))return u(),x;var $=["enter","move","leave"].indexOf(n)>=0,R=!z||O.get(d),E=!R&&W.get(d)||{},B=!!E.state;if(R||B&&E.state==s||(R=!D(t,g,n)),R)return u(),x;$&&F(t);var I={structural:$,element:t,event:n,close:u,options:h,runner:x};if(B){var H=e("skip",t,I,E);if(H)return E.state===o?(u(),x):(m(t,E.options,h),E.runner);var G=e("cancel",t,I,E);if(G)if(E.state===o)E.runner.end();else{if(!E.structural)return m(t,E.options,I.options),E.runner;E.close()}else{var _=e("join",t,I,E);if(_){if(E.state!==o)return b(t,$?n:null,h),n=I.event=E.event,h=m(t,E.options,I.options),E.runner;A(t,h)}}}else A(t,h);var N=I.structural;if(N||(N="animate"===I.event&&Object.keys(I.options.to||{}).length>0||i(I.options)),!N)return u(),T(t),x;var Y=(E.counter||0)+1;return I.counter=Y,M(t,s,I),r.$$postDigest(function(){var e=W.get(d),s=!e;e=e||{};var a=t.parent()||[],r=a.length>0&&("animate"===e.event||e.structural||i(e.options));if(s||e.counter!==Y||!r)return s&&(Q(t,h),p(t,h)),(s||$&&e.event!==n)&&(h.domOperation(),x.end()),void(r||T(t));n=!e.structural&&i(e.options,!0)?"setClass":e.event,M(t,o);var l=v(t,n,e.options);l.done(function(e){u(!e);var i=W.get(d);i&&i.counter===Y&&T(y(t)),c(x,n,"close",{})}),x.setHost(l),c(x,n,"start",{})}),x}function F(t){var e=y(t),i=e.querySelectorAll("["+At+"]");j(i,function(t){var e=parseInt(t.getAttribute(At)),i=W.get(t);switch(e){case o:i.runner.end();case s:i&&W.remove(t)}})}function T(t){var e=y(t);e.removeAttribute(At),W.remove(e)}function R(t,e){return y(t)===y(e)}function D(t,e,i){var n,s=H(u[0].body),o=R(t,s)||"HTML"===t[0].nodeName,a=R(t,c),r=!1,l=t.data(Lt);for(l&&(e=l);e&&e.length;){a||(a=R(e,c));var h=e[0];if(h.nodeType!==U)break;var d=W.get(h)||{};if(r||(r=d.structural||O.get(h)),G(n)||n===!0){var f=e.data(et);_(f)&&(n=f)}if(r&&n===!1)break;a||(a=R(e,c),a||(l=e.data(Lt),l&&(e=l))),o||(o=R(e,s)),e=e.parent()}var p=!r||n;return p&&a&&o}function M(t,e,i){i=i||{},i.state=e;var n=y(t);n.setAttribute(At,e);var s=W.get(n),o=s?I(s,i):i;W.put(n,o)}var W=new g,O=new g,z=null,E=r.$watch(function(){return 0===x.totalPendingRequests},function(t){t&&(E(),r.$$postDigest(function(){r.$$postDigest(function(){null===z&&(z=!0)})}))}),B={},N=t.classNameFilter(),J=N?function(t){return N.test(t)}:function(){return!0},Q=d(S);return{on:function(t,e,i){var n=h(e);B[t]=B[t]||[],B[t].push({node:n,callback:i})},off:function(t,e,i){function n(t,e,i){var n=h(e);return t.filter(function(t){var e=t.node===n&&(!i||t.callback===i);return!e})}var s=B[t];s&&(B[t]=1===arguments.length?null:n(s,e,i))},pin:function(t,e){n(Y(t),"element","not an element"),n(Y(e),"parentElement","not an element"),t.data(Lt,e)},push:function(t,e,i,n){return i=i||{},i.domOperation=n,$(t,e,i)},enabled:function(t,e){var i=arguments.length;if(0===i)e=!!z;else{var n=Y(t);if(n){var s=y(t),o=O.get(s);1===i?e=!o:(e=!!e,e?o&&O.remove(s):O.put(s,!0))}else e=z=!!t}return e}}}]}],Ft=["$$rAF",function(t){function e(e){i.push(e),i.length>1||t(function(){for(var t=0;t<i.length;t++)i[t]();i=[]})}var i=[];return function(){var t=!1;return e(function(){t=!0}),function(i){t?i():e(i)}}}],Tt=["$q","$sniffer","$$animateAsyncRun",function(t,e,i){function n(t){this.setHost(t),this._doneCallbacks=[],this._runInAnimationFrame=i(),this._state=0}var s=0,o=1,a=2;return n.chain=function(t,e){function i(){return n===t.length?void e(!0):void t[n](function(t){return t===!1?void e(!1):(n++,void i())})}var n=0;i()},n.all=function(t,e){function i(i){s=s&&i,++n===t.length&&e(s)}var n=0,s=!0;j(t,function(t){t.done(i)})},n.prototype={setHost:function(t){this.host=t||{}},done:function(t){this._state===a?t():this._doneCallbacks.push(t)},progress:B,getPromise:function(){if(!this.promise){var e=this;this.promise=t(function(t,i){e.done(function(e){e===!1?i():t()})})}return this.promise},then:function(t,e){return this.getPromise().then(t,e)},"catch":function(t){return this.getPromise()["catch"](t)},"finally":function(t){return this.getPromise()["finally"](t)},pause:function(){this.host.pause&&this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end(),this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel(),this._resolve(!1)},complete:function(t){var e=this;e._state===s&&(e._state=o,e._runInAnimationFrame(function(){e._resolve(t)}))},_resolve:function(t){this._state!==a&&(j(this._doneCallbacks,function(e){e(t)}),this._doneCallbacks.length=0,this._state=a)}},n}],Rt=["$animateProvider",function(t){function e(t,e){t.data(r,e)}function i(t){t.removeData(r)}function n(t){return t.data(r)}var o="ng-animate-ref",a=this.drivers=[],r="$$animationRunner";this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$HashMap","$$rAFScheduler",function(t,r,l,h,c,u){function g(t){function e(t){if(t.processed)return t;t.processed=!0;var i=t.domNode,n=i.parentNode;o.put(i,t);for(var a;n;){if(a=o.get(n)){a.processed||(a=e(a));break}n=n.parentNode}return(a||s).children.push(t),t}function i(t){var e,i=[],n=[];for(e=0;e<t.children.length;e++)n.push(t.children[e]);var s=n.length,o=0,a=[];for(e=0;e<n.length;e++){var r=n[e];0>=s&&(s=o,o=0,i.push(a),a=[]),a.push(r.fn),r.children.forEach(function(t){o++,n.push(t)}),s--}return a.length&&i.push(a),i}var n,s={children:[]},o=new c;for(n=0;n<t.length;n++){var a=t[n];o.put(a.domNode,t[n]={domNode:a.domNode,fn:a.fn,children:[]})}for(n=0;n<t.length;n++)e(t[n]);return i(s)}var v=[],m=d(t);return function(c,d,C){function b(t){var e="["+o+"]",i=t.hasAttribute(o)?[t]:t.querySelectorAll(e),n=[];return j(i,function(t){var e=t.getAttribute(o);e&&e.length&&n.push(t)}),n}function w(t){var e=[],i={};j(t,function(t,n){var s=t.element,a=y(s),r=t.event,l=["enter","move"].indexOf(r)>=0,h=t.structural?b(a):[];if(h.length){var c=l?"to":"from";j(h,function(t){var e=t.getAttribute(o);i[e]=i[e]||{},i[e][c]={animationID:n,element:H(t)}})}else e.push(t)});var n={},s={};return j(i,function(i,o){var a=i.from,r=i.to;if(!a||!r){var l=a?a.animationID:r.animationID,h=l.toString();return void(n[h]||(n[h]=!0,e.push(t[l])))}var c=t[a.animationID],u=t[r.animationID],d=a.animationID.toString();if(!s[d]){var f=s[d]={structural:!0,beforeStart:function(){c.beforeStart(),u.beforeStart()},close:function(){c.close(),u.close()},classes:x(c.classes,u.classes),from:c,to:u,anchors:[]};f.classes.length?e.push(f):(e.push(c),e.push(u))}s[d].anchors.push({out:a.element,"in":r.element})}),e}function x(t,e){t=t.split(" "),e=e.split(" ");for(var i=[],n=0;n<t.length;n++){var s=t[n];if("ng-"!==s.substring(0,3))for(var o=0;o<e.length;o++)if(s===e[o]){i.push(s);break}}return i.join(" ")}function S(t){for(var e=a.length-1;e>=0;e--){var i=a[e];if(l.has(i)){var n=l.get(i),s=n(t);if(s)return s}}}function P(){c.addClass(tt),R&&t.addClass(c,R)}function k(t,e){function i(t){n(t).setHost(e)}t.from&&t.to?(i(t.from.element),i(t.to.element)):i(t.element)}function A(){var t=n(c);!t||"leave"===d&&C.$$domOperationFired||t.end()}function L(e){c.off("$destroy",A),i(c),m(c,C),p(c,C),C.domOperation(),R&&t.removeClass(c,R),c.removeClass(tt),F.complete(!e)}C=f(C);var $=["enter","move","leave"].indexOf(d)>=0,F=new h({end:function(){L()},cancel:function(){L(!0)}});if(!a.length)return L(),F;e(c,F);var T=s(c.attr("class"),s(C.addClass,C.removeClass)),R=C.tempClasses;return R&&(T+=" "+R,C.tempClasses=null),v.push({element:c,classes:T,event:d,structural:$,options:C,beforeStart:P,close:L}),c.on("$destroy",A),v.length>1?F:(r.$$postDigest(function(){var t=[];j(v,function(e){n(e.element)?t.push(e):e.close()}),v.length=0;var e=w(t),i=[];j(e,function(t){i.push({domNode:y(t.from?t.from.element:t.element),fn:function(){t.beforeStart();var e,i=t.close,s=t.anchors?t.from.element||t.to.element:t.element;if(n(s)){var o=S(t);o&&(e=o.start)}if(e){var a=e();a.done(function(t){i(!t)}),k(t,a)}else i()}})}),u(g(i))}),F)}}]}];e.module("ngAnimate",[]).directive("ngAnimateChildren",gt).factory("$$rAFScheduler",pt).factory("$$AnimateRunner",Tt).factory("$$animateAsyncRun",Ft).provider("$$animateQueue",$t).provider("$$animation",Rt).provider("$animateCss",xt).provider("$$animateCssDriver",St).provider("$$animateJs",Pt).provider("$$animateJsDriver",kt)}(window,window.angular),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(t,e,i){this.groups=[],this.closeOthers=function(n){var s=angular.isDefined(e.closeOthers)?t.$eval(e.closeOthers):i.closeOthers;s&&angular.forEach(this.groups,function(t){t!==n&&(t.isOpen=!1)})},this.addGroup=function(t){var e=this;this.groups.push(t),t.$on("$destroy",function(i){e.removeGroup(t)})},this.removeGroup=function(t){var e=this.groups.indexOf(t);-1!==e&&this.groups.splice(e,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(t,e){return e.templateUrl||"template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,replace:!0,templateUrl:function(t,e){return e.templateUrl||"template/accordion/accordion-group.html"},scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(t){this.heading=t}},link:function(t,e,i,n){n.addGroup(t),t.openClass=i.openClass||"panel-open",t.panelClass=i.panelClass,t.$watch("isOpen",function(i){e.toggleClass(t.openClass,!!i),i&&n.closeOthers(t)}),t.toggleOpen=function(e){t.isDisabled||e&&32!==e.which||(t.isOpen=!t.isOpen)}}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(t,e,i,n,s){n.setHeading(s(t,angular.noop))}}}).directive("uibAccordionTransclude",function(){return{require:["?^uibAccordionGroup","?^accordionGroup"],link:function(t,e,i,n){n=n[0]?n[0]:n[1],t.$watch(function(){return n[i.uibAccordionTransclude]},function(t){t&&(e.find("span").html(""),e.find("span").append(t))})}}}),angular.module("ui.bootstrap.accordion").value("$accordionSuppressWarning",!1).controller("AccordionController",["$scope","$attrs","$controller","$log","$accordionSuppressWarning",function(t,e,i,n,s){s||n.warn("AccordionController is now deprecated. Use UibAccordionController instead."),angular.extend(this,i("UibAccordionController",{$scope:t,$attrs:e}))}]).directive("accordion",["$log","$accordionSuppressWarning",function(t,e){return{restrict:"EA",controller:"AccordionController",controllerAs:"accordion",transclude:!0,replace:!1,templateUrl:function(t,e){return e.templateUrl||"template/accordion/accordion.html"},link:function(){e||t.warn("accordion is now deprecated. Use uib-accordion instead.")}}}]).directive("accordionGroup",["$log","$accordionSuppressWarning",function(t,e){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:function(t,e){return e.templateUrl||"template/accordion/accordion-group.html"},scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(t){this.heading=t}},link:function(i,n,s,o){e||t.warn("accordion-group is now deprecated. Use uib-accordion-group instead."),o.addGroup(i),i.openClass=s.openClass||"panel-open",i.panelClass=s.panelClass,i.$watch("isOpen",function(t){n.toggleClass(i.openClass,!!t),t&&o.closeOthers(i)}),i.toggleOpen=function(t){i.isDisabled||t&&32!==t.which||(i.isOpen=!i.isOpen)}}}}]).directive("accordionHeading",["$log","$accordionSuppressWarning",function(t,e){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(i,n,s,o,a){e||t.warn("accordion-heading is now deprecated. Use uib-accordion-heading instead."),o.setHeading(a(i,angular.noop))}}}]).directive("accordionTransclude",["$log","$accordionSuppressWarning",function(t,e){return{require:"^accordionGroup",link:function(i,n,s,o){e||t.warn("accordion-transclude is now deprecated. Use uib-accordion-transclude instead."),i.$watch(function(){return o[s.accordionTransclude]},function(t){t&&(n.find("span").html(""),n.find("span").append(t))})}}}]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$injector",function(t,e){var i=e.has("$animateCss")?e.get("$animateCss"):null;return{link:function(e,n,s){function o(){n.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),i?i(n,{addClass:"in",easing:"ease",to:{height:n[0].scrollHeight+"px"}}).start()["finally"](a):t.addClass(n,"in",{to:{height:n[0].scrollHeight+"px"}}).then(a)}function a(){n.removeClass("collapsing").addClass("collapse").css({height:"auto"})}function r(){return n.hasClass("collapse")||n.hasClass("in")?(n.css({height:n[0].scrollHeight+"px"}).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),void(i?i(n,{removeClass:"in",to:{height:"0"}}).start()["finally"](l):t.removeClass(n,"in",{to:{height:"0"}}).then(l))):l()}function l(){n.css({height:"0"}),n.removeClass("collapsing").addClass("collapse")}e.$watch(s.uibCollapse,function(t){t?r():o()})}}}]),angular.module("ui.bootstrap.collapse").value("$collapseSuppressWarning",!1).directive("collapse",["$animate","$injector","$log","$collapseSuppressWarning",function(t,e,i,n){var s=e.has("$animateCss")?e.get("$animateCss"):null;return{link:function(e,o,a){function r(){o.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),s?s(o,{easing:"ease",to:{height:o[0].scrollHeight+"px"}}).start().done(l):t.animate(o,{},{height:o[0].scrollHeight+"px"}).then(l)}function l(){o.removeClass("collapsing").addClass("collapse in").css({height:"auto"})}function h(){return o.hasClass("collapse")||o.hasClass("in")?(o.css({height:o[0].scrollHeight+"px"}).removeClass("collapse in").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),void(s?s(o,{to:{height:"0"}}).start().done(c):t.animate(o,{},{height:"0"}).then(c))):c()}function c(){o.css({height:"0"}),o.removeClass("collapsing").addClass("collapse")}n||i.warn("collapse is now deprecated. Use uib-collapse instead."),e.$watch(a.collapse,function(t){t?h():r()})}}}]);
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/xosCeilometerDashboard.js b/xos/core/xoslib/static/js/xosCeilometerDashboard.js
index e44dc63..5aa7234 100644
--- a/xos/core/xoslib/static/js/xosCeilometerDashboard.js
+++ b/xos/core/xoslib/static/js/xosCeilometerDashboard.js
@@ -1 +1 @@
-"use strict";angular.module("xos.ceilometerDashboard",["ngResource","ngCookies","ngLodash","ui.router","xos.helpers","chart.js"]).config(["$stateProvider",function(e){e.state("ceilometerDashboard",{url:"/",template:"<ceilometer-dashboard></ceilometer-dashboard>"}).state("samples",{url:"/:name/:tenant/samples",template:"<ceilometer-samples></ceilometer-samples>"}).state("split",{url:"/split",controller:function(){console.log("split",Split),Split(["#one","#two","#three"],{})},templateUrl:"templates/split.html"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).service("Ceilometer",["$http","$q",function(e,i){this.getMeters=function(){var t=i.defer();return e.get("xoslib/meters/",{cache:!0}).then(function(e){t.resolve(e.data)})["catch"](function(e){t.reject(e)}),t.promise},this.getSamples=function(t,a){var s=i.defer();return e.get("xoslib/metersamples/",{params:{meter:t,tenant:a}}).then(function(e){s.resolve(e.data)})["catch"](function(e){s.reject(e)}),s.promise}}]).directive("ceilometerDashboard",["lodash",function(e){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-dashboard.tpl.html",controller:["Ceilometer",function(i){var t=this;this.loadMeters=function(){t.loader=!0,i.getMeters().then(function(i){t.projects=e.groupBy(i,"project_name"),e.forEach(Object.keys(t.projects),function(i){t.projects[i]=e.groupBy(t.projects[i],"resource_id")})})["catch"](function(e){t.err=e})["finally"](function(){t.loader=!1})},this.loadMeters()}]}}]).directive("ceilometerSamples",["lodash","$stateParams",function(e,i){return{restrict:"E",scope:{name:"=name",tenant:"=tenant"},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-samples.tpl.html",controller:["Ceilometer",function(t){var a=this;i.name&&i.tenant&&(this.name=i.name,this.tenant=i.tenant),this.formatDateLabels=function(e){return e},this.formatSamplesData=function(i){var t=[];return e.forEach(i,function(e){t.push({x:a.formatDateLabels(e.timestamp),y:[e.volume]})}),e.sortBy(t,"timestamp")},this.getLabels=function(e){return e.reduce(function(e,i){var t=new Date(i.timestamp);return e.push(t.getHours()+":"+((t.getMinutes()<10?"0":"")+t.getMinutes())+":"+t.getSeconds()),e},[])},this.getData=function(e){return e.reduce(function(e,i){return e.push(i.volume),e},[])},this.showSamples=function(){a.loader=!0,t.getSamples(a.name,a.tenant).then(function(i){i=e.sortBy(i,"timestamp"),a.chart={series:[a.name],labels:a.getLabels(i),data:[a.getData(i)]}})["catch"](function(e){console.warn(e)})["finally"](function(){a.loader=!1})},this.showSamples()}]}}]),angular.module("xos.ceilometerDashboard").run(["$templateCache",function(e){e.put("templates/ceilometer-dashboard.tpl.html",'<div class="row">\n <div class="col-sm-12">\n <h1>Ceilometer Dashboard</h1>\n </div>\n</div>\n\n<div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n</div>\n\n<section ng-hide="vm.loader">\n <div class="row">\n <div class="col-xs-12">\n <h2>Projects</h2>\n </div>\n </div>\n <div class="well" ng-repeat="(project, resources) in vm.projects">\n <div class="row">\n <div class="col-xs-11">\n <h3>{{project}}</h3>\n </div>\n <div class="col-xs-1">\n <a ng-click="expandProject = !expandProject" class="btn btn-primary">\n <i class="glyphicon glyphicon-plus"></i>\n </a>\n </div>\n </div>\n \n <div class="row">\n <div class="panel panel-default" ng-show="expandProject">\n <div class="panel-heading">\n <h4>Resources</h4>\n </div>\n <div class="panel-body" ng-repeat="(resource, meters) in resources">\n <div class="row">\n <div class="col-xs-11">\n <b>{{resource}}</b>\n </div>\n <div class="col-xs-1">\n <a ng-click="expandResource = !expandResource" class="btn btn-primary">\n <i class="glyphicon glyphicon-plus"></i>\n </a>\n </div>\n </div>\n <div class="row" ng-show="expandResource">\n <div class="col-xs-4">\n <b>Meter:</b>\n </div>\n <div class="col-xs-4">\n <b>Unit:</b>\n </div>\n <div class="col-xs-4">\n <b>Actions:</b>\n </div>\n </div>\n <div class="row" ng-repeat="meter in meters" ng-show="expandResource">\n <div class="col-xs-4">\n {{meter.name}}\n </div>\n <div class="col-xs-4">\n {{meter.unit}}\n </div>\n <div class="col-xs-4">\n <!-- <a ng-click="showMeter = !showMeter" class="btn btn-primary">\n <i class="glyphicon glyphicon-search"></i> Details\n </a> -->\n <a ng-click="showChart = !showChart" class="btn btn-primary">\n <i class="glyphicon glyphicon-search"></i> View chart\n </a>\n </div>\n <!-- -->\n <div class="col-xs-12" ng-show="showChart">\n <ceilometer-samples name="meter.name" tenant="meter.project_id" ng-if="showChart"></ceilometer-samples>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n</section>'),e.put("templates/ceilometer-samples.tpl.html",'<div class="row">\n <div class="col-xs-12" ng-show="vm.loader">\n <div class="loader">Loading</div>\n </div>\n\n <div class="col-xs-12" ng-if="!vm.loader">\n <!-- <div ac-chart="\'line\'" ac-data="vm.sampleChartData" ac-config="vm.sampleChartConfig" class="chart"></div> -->\n <canvas id="line" class="chart chart-line" chart-data="vm.chart.data"\n chart-labels="vm.chart.labels" chart-legend="true" chart-series="vm.chart.series">\n </canvas> \n <!-- <pre> {{ vm.chart | json }} </pre> -->\n </div>\n</div>'),e.put("templates/split.html",'<div id="one" class="split split-horizontal">\n Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, eos debitis repellendus corrupti vel dolores asperiores, ipsam voluptatibus nesciunt ipsum architecto harum magnam similique doloremque rerum illum. Magnam, nesciunt magni.\n Minus nostrum dolores perspiciatis dolorum eos? Sed, ad fugiat natus amet voluptas officiis, reiciendis tempora error quia repudiandae odit nisi distinctio atque ipsam iste officia ab porro et quo magni.\n Voluptatem ab rem necessitatibus nam voluptas quo, velit nobis id ea temporibus illum corrupti sequi, aperiam reprehenderit cum! Placeat quas quod minima expedita beatae totam numquam veritatis adipisci doloremque, sit.\n Suscipit doloremque voluptatum maiores architecto ipsa quis, nihil provident totam, quos qui. Ipsa quibusdam sit, cumque eum provident ratione molestiae quia in ex! Rem voluptates officiis aperiam ullam dignissimos sequi.\n Ad sed quasi et, dolorem autem perferendis dolor. Cupiditate nemo delectus minus sint mollitia accusantium odio, explicabo nihil illum ut possimus ducimus! Recusandae excepturi, est deleniti accusamus aut quasi. Sit!\n</div>\n<div id="two" class="split split-horizontal">\n Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit accusamus laboriosam, quo, ipsa quisquam, neque alias animi esse quia, doloremque nulla nihil. Id aliquid necessitatibus atque eum, fugit sed nobis!\n Blanditiis ab earum placeat tenetur in eos, omnis quidem accusantium voluptate corporis, labore, cum voluptatibus totam sunt mollitia et rerum sit. Voluptatem fugiat eaque dolore explicabo ex veritatis deleniti delectus.\n Nobis aliquam blanditiis cumque nesciunt repellendus voluptate ullam, eligendi dicta voluptates tenetur molestias omnis itaque eius voluptas dignissimos inventore repellat distinctio velit ducimus ipsam placeat. Quo amet aut, doloremque incidunt.\n Asperiores sed cupiditate animi aliquam, facilis vitae nobis deserunt ipsa fugiat, at incidunt eum delectus error inventore itaque fuga sunt aspernatur beatae saepe maxime id. Fuga consequatur hic debitis ipsum.\n Animi dolorum ullam, dolorem ut quibusdam tempora repellendus iste veritatis doloribus nam? Minima veritatis omnis deleniti illo? Vero, perferendis ipsum, ea dicta illum non reiciendis obcaecati sunt dolorem esse hic.\n</div>\n<div id="three" class="split split-horizontal">\n Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatem quod expedita vero voluptatibus modi, dolores assumenda ex atque aliquam accusamus, deserunt quibusdam pariatur eaque optio ducimus minima. Commodi, odit. Nulla.\n Rerum, nostrum, officiis! Nam vel in ea ut et nemo quae quis suscipit dolores voluptatum odio, qui ratione dolor vero perspiciatis enim incidunt error harum hic ad numquam nostrum magni.\n Minus illo vel ipsa, ullam unde itaque cum mollitia nihil! Voluptatibus quaerat ab ut quo, repudiandae qui reprehenderit eligendi maiores harum labore sit, laudantium expedita reiciendis hic nostrum beatae id!\n Laborum magni iusto sunt commodi dolor quis voluptatibus fugiat alias, aliquid fugit nisi facere. Eaque harum laudantium sint, veniam laborum illum beatae cumque quis reprehenderit tempore, animi perferendis officiis quos.\n Quam iusto id necessitatibus nam asperiores quod inventore itaque ullam laborum quis. Excepturi, suscipit, autem! Pariatur commodi nisi quia, sit perspiciatis necessitatibus, tempore neque nulla nemo eum aspernatur placeat voluptate!\n</div>')}]),angular.module("xos.ceilometerDashboard").run(["$location",function(e){e.path("/")}]),angular.bootstrap(angular.element("#xosCeilometerDashboard"),["xos.ceilometerDashboard"]);
\ No newline at end of file
+"use strict";angular.module("xos.ceilometerDashboard",["ngResource","ngCookies","ngLodash","ui.router","xos.helpers","ngAnimate","chart.js","ui.bootstrap.accordion"]).config(["$stateProvider","$urlRouterProvider",function(e,t){e.state("ceilometerDashboard",{url:"/",template:"<ceilometer-dashboard></ceilometer-dashboard>"}).state("samples",{url:"/:name/:tenant/samples",template:"<ceilometer-samples></ceilometer-samples>"}),t.otherwise("/")}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).run(["$rootScope",function(e){e.stateName="ceilometerDashboard",e.$on("$stateChangeStart",function(t,s){e.stateName=s.name})}]).service("Ceilometer",["$http","$q","lodash",function(e,t,s){var n=this;this.resourceMap={},this.getMeters=function(){var r=t.defer();return e.get("/xoslib/meters/",{cache:!0}).then(function(e){var t=s.groupBy(e.data,"resource_id");n.resourceMap=s.reduce(Object.keys(t),function(e,s){return e[s]=t[s][0].resource_name,e},{}),r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise},this.getSamples=function(s,n){var r=t.defer();return e.get("/xoslib/metersamples/",{params:{meter:s,tenant:n}}).then(function(e){r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise},this.getStats=function(n){var r=t.defer();return e.get("/xoslib/meterstatistics/",{cache:!0}).then(function(e){r.resolve(s.filter(e.data,{slice:n}))})["catch"](function(e){r.reject(e)}),r.promise}}]).directive("ceilometerDashboard",["lodash",function(e){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-dashboard.tpl.html",controller:["Ceilometer",function(t){var s=this;this.loadMeters=function(){s.loader=!0,t.getMeters().then(function(t){s.projects=e.groupBy(t,"service"),e.forEach(Object.keys(s.projects),function(t){s.projects[t]=e.groupBy(s.projects[t],"slice"),e.forEach(Object.keys(s.projects[t]),function(n){s.projects[t][n]=e.groupBy(s.projects[t][n],"resource_name")})})})["catch"](function(e){s.error=e.data.detail})["finally"](function(){s.loader=!1})},this.loadMeters(),this.selectService=function(e){s.selectedResources=null,s.selectedResource=null,s.selectedMeters=null,s.selectedService=e},this.selectedResources=null,this.selectResources=function(e,t){s.selectedResources=null,s.selectedResource=null,s.selectedMeters=null,s.selectedResources=e,s.selectedSlice=t},this.selectedMeters=null,this.selectMeters=function(e,t){s.selectedMeters=e,s.selectedResource=t}}]}}]).directive("ceilometerSamples",["lodash","$stateParams",function(e,t){return{restrict:"E",scope:{name:"=name",tenant:"=tenant"},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-samples.tpl.html",controller:["Ceilometer",function(s){var n=this;if(this.chartColors=["#286090","#F7464A","#46BFBD","#FDB45C","#97BBCD","#4D5360","#8c4f9f"],this.chart={series:[],labels:[],data:[]},Chart.defaults.global.colours=this.chartColors,this.chartType="line",!t.name||!t.tenant)throw new Error("Missing Name and Tenant Params!");this.name=t.name,this.tenant=t.tenant,this.getLabels=function(e){return e.reduce(function(e,t){var s=new Date(t.timestamp);return e.push(s.getHours()+":"+((s.getMinutes()<10?"0":"")+s.getMinutes())+":"+s.getSeconds()),e},[])},this.getData=function(e){return e.reduce(function(e,t){return e.push(t.volume),e},[])},this.chartMeters=[],this.addMeterToChart=function(t){n.chart.labels=n.getLabels(e.sortBy(n.samplesList[t],"timestamp")),n.chart.series.push(t),n.chart.data.push(n.getData(e.sortBy(n.samplesList[t],"timestamp"))),n.chartMeters.push(n.samplesList[t][0]),e.remove(n.sampleLabels,{id:t})},this.removeFromChart=function(t){n.chart.data.splice(n.chart.series.indexOf(t.resource_id),1),n.chart.series.splice(n.chart.series.indexOf(t.resource_id),1),n.chartMeters.splice(e.findIndex(n.chartMeters,{resource_id:t.resource_id}),1),n.sampleLabels.push({id:t.resource_id,name:t.resource_name})},this.formatSamplesLabels=function(t){return e.uniq(t,"resource_id").reduce(function(e,t){return e.push({id:t.resource_id,name:t.resource_name}),e},[])},this.showSamples=function(){n.loader=!0,s.getSamples(n.name).then(function(t){n.samplesList=e.groupBy(t,"resource_id"),n.sampleLabels=n.formatSamplesLabels(t),n.addMeterToChart(n.tenant)})["catch"](function(e){n.error=e.data.detail})["finally"](function(){n.loader=!1})},this.showSamples()}]}}]).directive("ceilometerStats",function(){return{restrict:"E",scope:{name:"=name"},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-stats.tpl.html",controller:["$scope","Ceilometer",function(e,t){var s=this;this.getStats=function(){s.loader=!0,t.getStats(s.name).then(function(e){s.stats=e})["catch"](function(e){s.error=e.data})["finally"](function(){s.loader=!1})},this.getStats(),e.$watch(function(){return s.name},function(){s.getStats()})}]}}).filter("orderObjectByKey",["lodash",function(e){return function(t){return t?e.reduce(Object.keys(t).reverse(),function(e,s){return e[s]=t[s],e},{}):void 0}}]),angular.module("xos.ceilometerDashboard").run(["$templateCache",function(e){e.put("templates/accordion-group.html",'<div class="panel {{panelClass || \'panel-default\'}}">\n <div class="panel-heading" ng-keypress="toggleOpen($event)">\n <h3>\n <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n </h3>\n </div>\n <div class="panel-collapse collapse" uib-collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n </div>\n</div>\n'),e.put("templates/accordion.html",'<div class="panel-group" ng-transclude></div>'),e.put("templates/ceilometer-dashboard.tpl.html",'<div class="row">\n <div class="col-sm-10">\n <h1>XOS Monitoring Statistics</h1>\n </div>\n <div class="col-xs-2 text-right">\n <a href="" class="btn btn-default" \n ng-show="vm.selectedResources && !vm.showStats"\n ng-click="vm.showStats = true">\n <i class="glyphicon glyphicon-transfer"></i>\n </a>\n <a href="" class="btn btn-default" \n ng-show="vm.selectedResources && vm.showStats"\n ng-click="vm.showStats = false">\n <i class="glyphicon glyphicon-transfer"></i>\n </a>\n </div>\n</div>\n\n<div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n</div>\n\n<section ng-hide="vm.loader" ng-class="{animate: !vm.loader}">\n <div class="row">\n <div class="col-sm-3 service-list">\n <h3>XOS Service: </h3>\n <uib-accordion close-others="true" template-url="templates/accordion.html">\n <uib-accordion-group\n ng-repeat="(service, slices) in vm.projects | orderObjectByKey"\n template-url="templates/accordion-group.html"\n heading="{{service}}">\n <h4>Slices:</h4>\n <a ng-repeat="(slice, resources) in slices" \n ng-class="{active: slice === vm.selectedSlice}"\n ng-click="vm.selectResources(resources, slice)"\n href="#" class="list-group-item" >\n {{slice}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>\n </a>\n </uib-accordion-group>\n </uib-accordion>\n </div>\n <section class="side-container col-sm-9">\n <div class="row">\n <article ng-hide="!vm.showStats" class="stats animate-slide-left">\n <div class="col-xs-12">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Stats</h3>\n </div>\n <div class="list-group-item">\n <ceilometer-stats ng-if="vm.selectedSlice" name="vm.selectedSlice"></ceilometer-stats>\n </div>\n </div>\n </div>\n </article>\n <article ng-hide="vm.showStats" class="meters animate-slide-left">\n <div class="col-sm-4 animate-slide-left" ng-hide="!vm.selectedResources">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Resources</h3>\n </div>\n <a href="#" \n ng-click="vm.selectMeters(meters, resource)" \n class="list-group-item" \n ng-repeat="(resource, meters) in vm.selectedResources" \n ng-class="{active: resource === vm.selectedResource}">\n {{resource}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>\n </a>\n </div>\n </div>\n <div class="col-sm-8 animate-slide-left" ng-hide="!vm.selectedMeters">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Meters</h3>\n </div>\n <div class="list-group-item">\n <div class="row">\n <div class="col-xs-6">\n <label>Name:</label>\n </div>\n <div class="col-xs-3">\n <label>Unit:</label>\n </div>\n <div class="col-xs-3"></div>\n </div>\n <div class="row" ng-click="vm.selectMeters(meters)" ng-repeat="meter in vm.selectedMeters" style="margin-bottom: 10px;">\n <div class="col-xs-6">\n {{meter.name}}\n </div>\n <div class="col-xs-3">\n {{meter.unit}}\n </div>\n <div class="col-xs-3">\n <a ui-sref="samples({name: meter.name, tenant: meter.resource_id})" class="btn btn-primary">\n <i class="glyphicon glyphicon-search"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </article>\n </div>\n </section>\n </div>\n</section>\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>\n'),e.put("templates/ceilometer-samples.tpl.html",'<!-- <pre>{{ vm | json}}</pre> -->\n\n<div class="row">\n <div class="col-xs-10">\n <h1>{{vm.name | uppercase}}</h1>\n </div>\n <div class="col-xs-2">\n <a ui-sref="ceilometerDashboard" class="btn btn-primary pull-right">\n <i class="glyphicon glyphicon-arrow-left"></i> Back to list\n </a>\n </div>\n</div>\n<div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n</div>\n<section ng-if="!vm.loader && !vm.error">\n <div class="row">\n <form class="form-inline col-xs-8" ng-submit="vm.addMeterToChart(vm.addMeterValue)">\n <select ng-model="vm.addMeterValue" class="form-control" ng-options="resource.id as resource.name for resource in vm.sampleLabels"></select>\n <button class="btn btn-success"> \n <i class="glyphicon glyphicon-plus"></i> Add\n </button>\n </form>\n <div class="col-xs-4 text-right">\n <a ng-click="vm.chartType = \'line\'" class="btn" ng-class="{\'btn-default\': vm.chartType != \'bar\', \'btn-primary\': vm.chartType == \'line\'}">Lines</a>\n <a ng-click="vm.chartType = \'bar\'" class="btn" ng-class="{\'btn-default\': vm.chartType != \'line\', \'btn-primary\': vm.chartType == \'bar\'}">Bars</a>\n </div>\n </div>\n <div class="row" ng-if="!vm.loader">\n <div class="col-xs-12">\n <canvas ng-if="vm.chartType === \'line\'" id="line" class="chart chart-line" chart-data="vm.chart.data" chart-options="{datasetFill: false}"\n chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">\n </canvas>\n <canvas ng-if="vm.chartType === \'bar\'" id="bar" class="chart chart-bar" chart-data="vm.chart.data"\n chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">\n </canvas>\n <!-- <pre>{{vm.chartMeters | json}}</pre> -->\n </div>\n </div>\n <div class="row" ng-if="!vm.loader">\n <div class="col-xs-12">\n <a ng-click="vm.removeFromChart(meter)" class="btn btn-chart" ng-style="{\'background-color\': vm.chartColors[$index]}" ng-repeat="meter in vm.chartMeters">\n {{meter.resource_name}}\n </a>\n </div>\n </div>\n</section>\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>'),e.put("templates/ceilometer-stats.tpl.html",'<div ng-show="vm.loader" class="loader">Loading</div>\n\n<section ng-if="!vm.loader && !vm.error">\n\n <div class="alert alert-danger" ng-if="vm.stats.length == 0">\n No result\n </div> \n\n <table class="table" ng-if="vm.stats.length > 0">\n <tr>\n <th>Type:</th>\n <th>Meter:</th>\n <th>Unit:</th>\n <th>Value:</th>\n </tr>\n <tr ng-repeat="item in vm.stats">\n <td>{{item.type}}</td>\n <td>{{item.meter}}</td>\n <td>{{item.unit}}</td>\n <td>{{item.value}}</td>\n </tr>\n </table>\n</section>\n\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>\n')}]),angular.module("xos.ceilometerDashboard").run(["$location",function(e){e.path("/")}]),angular.bootstrap(angular.element("#xosCeilometerDashboard"),["xos.ceilometerDashboard"]);
\ No newline at end of file
diff --git a/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py b/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py
index 9329cfa..62f0804 100644
--- a/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py
+++ b/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py
@@ -5,6 +5,8 @@
import json
from ceilometerclient import client
import logging
+import urllib
+import urllib2
from wsgilog import WsgiLog
web.config.debug=False
@@ -49,6 +51,7 @@
r'^/v2/meters/(?P<meter_name>[A-Za-z0-9_:.\-]+)/statistics$', 'statistics_list',
r'^/v2/samples$', 'sample_list',
r'^/v2/resources$', 'resource_list',
+ r'^/v2/subscribe$', 'pubsub_handler',
)
app = web.application(urls, globals())
@@ -245,5 +248,36 @@
resources.extend(results)
return json.dumps([ob._info for ob in resources])
+class pubsub_handler:
+ def POST(self):
+ global config
+ parse_ceilometer_proxy_config()
+ data_str = unicode(web.data(),'iso-8859-1')
+ post_data = json.loads(data_str)
+ final_query=[]
+ for (k,v) in config.items('allowed_tenants'):
+ query = make_query(tenant_id=k)
+ final_query.extend(query)
+ if not final_query:
+ raise Exception("Not allowed to subscribe to any meters")
+ post_data["query"] = final_query
+ #TODO: The PUB/SUB url needs to be read from config
+ put_request = urllib2.Request("http://10.11.10.1:4455/subscribe", json.dumps(post_data))
+ put_request.get_method = lambda: 'SUB'
+ put_request.add_header('Content-Type', 'application/json')
+ response = urllib2.urlopen(put_request)
+ response_text = response.read()
+ return json.dumps(response_text)
+
+ def DELETE(self):
+ data_str = web.data()
+ #TODO: The PUB/SUB url needs to be read from config
+ put_request = urllib2.Request("http://10.11.10.1:4455/unsubscribe", data_str)
+ put_request.get_method = lambda: 'UNSUB'
+ put_request.add_header('Content-Type', 'application/json')
+ response = urllib2.urlopen(put_request)
+ response_text = response.read()
+ return json.dumps(response_text)
+
if __name__ == "__main__":
app.run(FileLog)
diff --git a/xos/observers/monitoring_channel/templates/ceilometer_pub_sub_consumer.py b/xos/observers/monitoring_channel/templates/ceilometer_pub_sub_consumer.py
new file mode 100644
index 0000000..ecbabb9
--- /dev/null
+++ b/xos/observers/monitoring_channel/templates/ceilometer_pub_sub_consumer.py
@@ -0,0 +1,212 @@
+import socket
+import requests
+import urllib2
+import json
+import msgpack
+import collections
+import time, thread, threading
+
+projects_map = {}
+
+UDP_IP = "0.0.0.0"
+UDP_PORT = 12346
+
+def acquire_xos_monitoring_channel():
+ url = "http://ctl:9999/xoslib/monitoringchannel/"
+ admin_auth=("padmin@vicci.org", "letmein") # use your XOS username and password
+ monitoring_channels = requests.get(url, auth=admin_auth).json()
+ ceilometer_url = None
+ if not monitoring_channels:
+ print 'SRIKANTH: No monitoring channels for this user...'
+ return None
+ else:
+ monitoring_channel = monitoring_channels[0]
+ while not monitoring_channel['ceilometer_url']:
+ print 'SRIKANTH: Waiting for monitoring channel create'
+ sleep(0.5)
+ monitoring_channel = requests.get(url, auth=admin_auth).json()[0]
+ #TODO: Wait until URL is completely UP
+ while True:
+ print 'SRIKANTH: Waiting for ceilometer proxy URL %s is available' % monitoring_channel['ceilometer_url']
+ try:
+ response = urllib2.urlopen(monitoring_channel['ceilometer_url'],timeout=1)
+ break
+ except urllib2.HTTPError, e:
+ print 'SRIKANTH: HTTP error %s' % e.reason
+ break
+ except urllib2.URLError, e:
+ print 'SRIKANTH: URL error %(reason)s' % e.reason
+ pass
+ return monitoring_channel
+
+def print_samples():
+ print ""
+ print ""
+ for project in projects_map.keys():
+ print "project=%s, alarm_state=%s" % (project, projects_map[project]['alarm'])
+ for resource in projects_map[project]['resources'].keys():
+ print "resource=%s" % resource
+ for i in projects_map[project]['resources'][resource]:
+ print " time=%s val=%s" % ( i['timestamp'],i['counter_volume'])
+
+def periodic_print():
+ print_samples()
+ #Print every 1minute
+ threading.Timer(60, periodic_print).start()
+
+
+CPU_UPPER_THRESHOLD = 80 #80%
+CPU_LOWER_THRESHOLD = 30 #30%
+CPU_THRESHOLD_REPEAT = 3
+INITIAL_STATE = 'normal_config'
+SCALE_UP_EVALUATION = 'scale_up_eval'
+SCALE_DOWN_EVALUATION = 'scale_down_eval'
+SCALE_UP_ALARM = 'scale_up'
+SCALE_DOWN_ALARM = 'scale_down'
+
+def getXosTenantInfo(project):
+ print "SRIKANTH: Getting XOS info for openstack Project %s" % project
+ url = "http://ctl:9999/xos/controllerslices/"
+ admin_auth=("padmin@vicci.org", "letmein") # use your XOS username and password
+ controller_slices = requests.get(url, auth=admin_auth).json()
+ for cslice in controller_slices:
+ if cslice['tenant_id'] == project:
+ print "SRIKANTH: Matching controller_slice=%s" % cslice['humanReadableName']
+ slice = requests.get(cslice['slice'], auth=admin_auth).json()
+ slice_name = slice['humanReadableName']
+ print "SRIKANTH: Matching slice=%s" % slice_name
+ service = requests.get(slice['service'], auth=admin_auth).json()
+ service_name = service['humanReadableName']
+ print "SRIKANTH: Matching service=%s" % service_name
+ return {'service':service_name, 'slice':slice_name}
+ logger.warn("SRIKANTH: Project %(project)s has no associated XOS slice" % {'project':project})
+ return None
+
+def handle_adjust_scale(project, adjust):
+ if (adjust != 'up') and (adjust != 'down'):
+ print "SRIKANTH: Invalid adjust value %s " % adjust
+ return
+ current_instances = len(projects_map[project]['resources'].keys())
+ if (current_instances <=1 and adjust == 'down'):
+ print "SRIKANTH: %s is running with already minimum instances and can not scale down further " % project
+ return
+ if (current_instances >=2 and adjust == 'up'):
+ print "SRIKANTH: %s is running with already maximum instances and can not scale up further " % project
+ return
+ xos_tenant = getXosTenantInfo(project)
+ if not xos_tenant:
+ print "SRIKANTH: Can not handle adjust_scale for Project %s because not associated with any slice" % project
+ return
+ xos_service = xos_tenant['service']
+ xos_slice = xos_tenant['slice']
+ if not xos_service or not xos_slice:
+ print "SRIKANTH: Can not handle adjust_scale for Project %s because not associated with any service or slice" % project
+ return
+ print "SRIKANTH: SCALE %s for Project %s, Slice=%s, Service=%s from current=%d to new=%d" % (adjust, project, xos_slice, xos_service, current_instances, current_instances+1 if (adjust=='up') else current_instances-1)
+ query_params = {'service':xos_service, 'slice_hint':xos_slice, 'scale':current_instances+1 if (adjust=='up') else current_instances-1}
+ url = "http://ctl:9999/xoslib/serviceadjustscale/"
+ admin_auth=("padmin@vicci.org", "letmein") # use your XOS username and password
+ response = requests.get(url, params=query_params, auth=admin_auth).json()
+ print "SRIKANTH: XOS adjust_scale response: %s" % response
+
+def periodic_cpu_threshold_evaluator():
+ for project in projects_map.keys():
+ aggregate_cpu_util = sum([resource_queue[-1]['counter_volume'] \
+ for resource_queue in projects_map[project]['resources'].values()]) \
+ /len(projects_map[project]['resources'].keys())
+
+ if (projects_map[project]['alarm'] == INITIAL_STATE or
+ projects_map[project]['alarm'] == SCALE_UP_ALARM or
+ projects_map[project]['alarm'] == SCALE_DOWN_ALARM):
+ if aggregate_cpu_util > CPU_UPPER_THRESHOLD:
+ projects_map[project]['uthreadshold_count'] = 1
+ projects_map[project]['alarm'] = SCALE_UP_EVALUATION
+ if projects_map[project]['uthreadshold_count'] >= CPU_THRESHOLD_REPEAT:
+ projects_map[project]['alarm'] = SCALE_UP_ALARM
+ handle_adjust_scale(project, 'up')
+ elif aggregate_cpu_util < CPU_LOWER_THRESHOLD:
+ projects_map[project]['lthreadshold_count'] = 1
+ projects_map[project]['alarm'] = SCALE_DOWN_EVALUATION
+ if projects_map[project]['lthreadshold_count'] >= CPU_THRESHOLD_REPEAT:
+ projects_map[project]['alarm'] = SCALE_DOWN_ALARM
+ handle_adjust_scale(project, 'down')
+ else:
+ projects_map[project]['uthreadshold_count'] = 0
+ projects_map[project]['lthreadshold_count'] = 0
+ projects_map[project]['alarm'] = INITIAL_STATE
+ elif projects_map[project]['alarm'] == SCALE_UP_EVALUATION:
+ if aggregate_cpu_util > CPU_UPPER_THRESHOLD:
+ projects_map[project]['uthreadshold_count'] += 1
+ if projects_map[project]['uthreadshold_count'] >= CPU_THRESHOLD_REPEAT:
+ projects_map[project]['alarm'] = SCALE_UP_ALARM
+ handle_adjust_scale(project, 'up')
+ elif aggregate_cpu_util < CPU_LOWER_THRESHOLD:
+ projects_map[project]['lthreadshold_count'] += 1
+ projects_map[project]['alarm'] = SCALE_DOWN_EVALUATION
+ else:
+ projects_map[project]['uthreadshold_count'] = 0
+ projects_map[project]['alarm'] = INITIAL_STATE
+ elif projects_map[project]['alarm'] == SCALE_DOWN_EVALUATION:
+ if aggregate_cpu_util < CPU_LOWER_THRESHOLD:
+ projects_map[project]['lthreadshold_count'] += 1
+ if projects_map[project]['lthreadshold_count'] >= CPU_THRESHOLD_REPEAT:
+ projects_map[project]['alarm'] = SCALE_DOWN_ALARM
+ handle_adjust_scale(project, 'down')
+ elif aggregate_cpu_util > CPU_UPPER_THRESHOLD:
+ projects_map[project]['uthreadshold_count'] += 1
+ projects_map[project]['alarm'] = SCALE_UP_EVALUATION
+ else:
+ projects_map[project]['lthreadshold_count'] = 0
+ projects_map[project]['alarm'] = INITIAL_STATE
+ threading.Timer(60, periodic_cpu_threshold_evaluator).start()
+
+def read_notification_from_ceilometer(host,port):
+ udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
+ udp.bind((host, port))
+
+ while True:
+ data, source = udp.recvfrom(64000)
+ try:
+ sample = msgpack.loads(data, encoding='utf-8')
+ if sample['counter_name'] != 'cpu_util':
+ continue
+ if sample['project_id'] not in projects_map.keys():
+ projects_map[sample['project_id']] = {}
+ projects_map[sample['project_id']]['resources'] = {}
+ projects_map[sample['project_id']]['uthreadshold_count'] = 0
+ projects_map[sample['project_id']]['lthreadshold_count'] = 0
+ projects_map[sample['project_id']]['alarm'] = INITIAL_STATE
+ resource_map = projects_map[sample['project_id']]['resources']
+ if sample['resource_id'] not in resource_map.keys():
+ resource_map[sample['resource_id']] = collections.deque(maxlen=10)
+ samples_map = resource_map[sample['resource_id']]
+ sample = {'counter_name':sample['counter_name'],
+ 'project_id':sample['project_id'],
+ 'resource_id':sample['resource_id'],
+ 'timestamp':sample['timestamp'],
+ 'counter_unit':sample['counter_unit'],
+ 'counter_volume':sample['counter_volume']}
+ samples_map.append(sample)
+ except Exception as e:
+ print e
+
+def main():
+ monitoring_channel = acquire_xos_monitoring_channel()
+ if not monitoring_channel:
+ print 'SRIKANTH: XOS monitoring_channel is not created... Create it before using this app'
+ return
+ thread.start_new(read_notification_from_ceilometer,(UDP_IP,UDP_PORT,))
+ ceilometer_url = monitoring_channel['ceilometer_url']
+ subscribe_data = {"sub_info":"cpu_util","app_id":"xos_auto_scale","target":"udp://10.11.10.1:12346"}
+ subscribe_url = ceilometer_url + 'v2/subscribe'
+ response = requests.post(subscribe_url, data=json.dumps(subscribe_data))
+ print 'SRIKANTH: Ceilometer Subscription status:%s' % response.text
+ #TODO: Fix the typo in 'sucess'
+ if (not 'sucess' in response.text) and (not 'already exists' in response.text):
+ print 'SRIKANTH: Ceilometer Subscription unsuccessful...Exiting'
+ return
+ periodic_cpu_threshold_evaluator()
+ periodic_print()
+
+if __name__ == "__main__":
+ main()
diff --git a/xos/observers/vtn/model-deps b/xos/observers/vtn/model-deps
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/xos/observers/vtn/model-deps
@@ -0,0 +1 @@
+{}
diff --git a/xos/observers/vtn/run.sh b/xos/observers/vtn/run.sh
new file mode 100755
index 0000000..d7e5025
--- /dev/null
+++ b/xos/observers/vtn/run.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+python vtn-observer.py -C $XOS_DIR/observers/vtn/vtn_observer_config
diff --git a/xos/observers/vtn/start.sh b/xos/observers/vtn/start.sh
new file mode 100755
index 0000000..168074d
--- /dev/null
+++ b/xos/observers/vtn/start.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+nohup python vtn-observer.py -C $XOS_DIR/observers/vtn/vtn_observer_config > /dev/null 2>&1 &
diff --git a/xos/observers/vtn/steps/sync_tenant.py b/xos/observers/vtn/steps/sync_tenant.py
new file mode 100644
index 0000000..45f8722
--- /dev/null
+++ b/xos/observers/vtn/steps/sync_tenant.py
@@ -0,0 +1,48 @@
+import os
+import requests
+import socket
+import sys
+import base64
+from django.db.models import F, Q
+from xos.config import Config
+from observer.syncstep import SyncStep
+from core.models import Service
+from core.models.service import COARSE_KIND
+from cord.models import Tenant
+from util.logger import Logger, logging
+
+# hpclibrary will be in steps/..
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+logger = Logger(level=logging.INFO)
+
+class SyncTenant(SyncStep):
+ provides=[Tenant]
+ observes=Tenant
+ requested_interval=0
+
+ def __init__(self, **args):
+ SyncStep.__init__(self, **args)
+ self.saved_vtn_maps = [] # TODO: load this
+
+ def call(self, **args):
+ logger.info("sync'ing vtn services")
+ for service in Service.objects.all():
+ for id in service.get_vtn_src_ids():
+ dependencies = service.get_vtn_dependencies_ids()
+ if dependencies:
+ for dependency in dependencies:
+ vtn_maps.append( (id, dependency) )
+
+ for vtn_map in vtn_maps:
+ if not (vtn_map in self.saved_vtn_maps):
+ pass # call vtn rest api to add map
+
+ for vtn_map in self.saved_vtn_maps:
+ if not vtn_map in vtn_maps:
+ pass # call vtn rest api to delete map
+
+ self.saved_vtn_maps = vtn_maps
+ # TODO: save this
+
diff --git a/xos/observers/vtn/stop.sh b/xos/observers/vtn/stop.sh
new file mode 100755
index 0000000..261f029
--- /dev/null
+++ b/xos/observers/vtn/stop.sh
@@ -0,0 +1 @@
+pkill -9 -f vtn-observer.py
diff --git a/xos/observers/vtn/supervisor/vtn-observer.conf b/xos/observers/vtn/supervisor/vtn-observer.conf
new file mode 100644
index 0000000..714afa7
--- /dev/null
+++ b/xos/observers/vtn/supervisor/vtn-observer.conf
@@ -0,0 +1,2 @@
+[program:vtn-observer]
+command=python /opt/xos/observers/vbng/vtn-observer.py -C /opt/xos/observers/vbng/vtn_observer_config
diff --git a/xos/observers/vtn/vtn-observer.py b/xos/observers/vtn/vtn-observer.py
new file mode 100755
index 0000000..d6a71ff
--- /dev/null
+++ b/xos/observers/vtn/vtn-observer.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+# This imports and runs ../../xos-observer.py
+
+import importlib
+import os
+import sys
+observer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),"../..")
+sys.path.append(observer_path)
+mod = importlib.import_module("xos-observer")
+mod.main()
diff --git a/xos/observers/vtn/vtn_observer_config b/xos/observers/vtn/vtn_observer_config
new file mode 100644
index 0000000..19e9a39
--- /dev/null
+++ b/xos/observers/vtn/vtn_observer_config
@@ -0,0 +1,38 @@
+
+[plc]
+name=plc
+deployment=VICCI
+
+[db]
+name=xos
+user=postgres
+password=password
+host=localhost
+port=5432
+
+[api]
+host=128.112.171.237
+port=8000
+ssl_key=None
+ssl_cert=None
+ca_ssl_cert=None
+ratelimit_enabled=0
+omf_enabled=0
+mail_support_address=support@localhost
+nova_enabled=True
+
+[observer]
+name=vtn
+dependency_graph=/opt/xos/observers/vtn/model-deps
+steps_dir=/opt/xos/observers/vtn/steps
+sys_dir=/opt/xos/observers/vtn/sys
+deleters_dir=/opt/xos/observers/vtn/deleters
+log_file=console
+#/var/log/hpc.log
+driver=None
+pretend=False
+backoff_disabled=True
+
+[feefie]
+client_id='vicci_dev_central'
+user_id='pl'
diff --git a/xos/openstack_observer/steps/sync_container.py b/xos/openstack_observer/steps/sync_container.py
index 272e5f8..039fb55 100644
--- a/xos/openstack_observer/steps/sync_container.py
+++ b/xos/openstack_observer/steps/sync_container.py
@@ -103,7 +103,10 @@
def get_extra_attributes(self, o):
fields={}
fields["ansible_tag"] = "container-%s" % str(o.id)
- fields["docker_image"] = o.image.name
+ if o.image.tag:
+ fields["docker_image"] = o.image.path + ":" + o.image.tag
+ else:
+ fields["docker_image"] = o.image.path
fields["ports"] = self.get_ports(o)
if o.volumes:
fields["volumes"] = [x.strip() for x in o.volumes.split(",")]
diff --git a/xos/openstack_observer/steps/sync_controller_networks.py b/xos/openstack_observer/steps/sync_controller_networks.py
index ef238ee..b646936 100644
--- a/xos/openstack_observer/steps/sync_controller_networks.py
+++ b/xos/openstack_observer/steps/sync_controller_networks.py
@@ -66,7 +66,8 @@
def map_sync_inputs(self, controller_network):
- if (controller_network.network.template.name!='Private'):
+ # XXX This check should really be made from booleans, rather than using hardcoded network names
+ if (controller_network.network.template.name not in ['Private', 'Private-Indirect', 'Private-Direct']):
logger.info("skipping network controller %s because it is not private" % controller_network)
# We only sync private networks
return SyncStep.SYNC_WITHOUT_RUNNING
@@ -81,7 +82,8 @@
raise Exception('Could not save network controller %s'%controller_network)
def map_delete_inputs(self, controller_network):
- if (controller_network.network.template.name!='Private'):
+ # XXX This check should really be made from booleans, rather than using hardcoded network names
+ if (controller_network.network.template.name not in ['Private', 'Private-Indirect', 'Private-Direct']):
# We only sync private networks
return
try:
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index a806327..10910fb 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -93,6 +93,21 @@
properties:
xos_base_service_props
+ tosca.nodes.Tenant:
+ derived_from: tosca.nodes.Root
+ description: >
+ An ONOS Tenant.
+ properties:
+ xos_base_tenant_props
+ service_specific_attribute:
+ type: string
+ required: false
+ description: Service-specific attribute, usually a string containing a json dictionary
+ model:
+ type: string
+ required: false
+ description: Name of model to use when instantiating tenant
+
tosca.nodes.ONOSService:
derived_from: tosca.nodes.Root
description: >
@@ -350,6 +365,10 @@
type: string
required: false
description: Indicates the type of controller that the network is connected to.
+ access:
+ type: string
+ required: false
+ description: The type of access semantics for this network
tosca.nodes.network.Network.XOS:
# Due to bug? in implementation, we have to copy everything from
@@ -484,7 +503,11 @@
path:
type: string
required: false
- description: Path to Image file inside XOS docker container.
+ description: Path to Image file
+ tag:
+ type: string
+ required: false
+ description: For Docker images, tag of image
tosca.nodes.Controller:
derived_from: tosca.nodes.Root
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 3339fdf..4c12e7f 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -61,6 +61,28 @@
required: false
description: Version number of Service.
+ tosca.nodes.Tenant:
+ derived_from: tosca.nodes.Root
+ description: >
+ An ONOS Tenant.
+ properties:
+ kind:
+ type: string
+ default: generic
+ description: Kind of tenant
+ service_specific_id:
+ type: string
+ required: false
+ description: Service specific ID opaque to XOS but meaningful to service
+ service_specific_attribute:
+ type: string
+ required: false
+ description: Service-specific attribute, usually a string containing a json dictionary
+ model:
+ type: string
+ required: false
+ description: Name of model to use when instantiating tenant
+
tosca.nodes.ONOSService:
derived_from: tosca.nodes.Root
description: >
@@ -494,6 +516,10 @@
type: string
required: false
description: Indicates the type of controller that the network is connected to.
+ access:
+ type: string
+ required: false
+ description: The type of access semantics for this network
tosca.nodes.network.Network.XOS:
# Due to bug? in implementation, we have to copy everything from
@@ -639,7 +665,11 @@
path:
type: string
required: false
- description: Path to Image file inside XOS docker container.
+ description: Path to Image file
+ tag:
+ type: string
+ required: false
+ description: For Docker images, tag of image
tosca.nodes.Controller:
derived_from: tosca.nodes.Root
diff --git a/xos/tosca/resources/image.py b/xos/tosca/resources/image.py
index 938c5cd..fcd53b4 100644
--- a/xos/tosca/resources/image.py
+++ b/xos/tosca/resources/image.py
@@ -15,7 +15,7 @@
class XOSImage(XOSResource):
provides = "tosca.nodes.Image"
xos_model = Image
- copyin_props = ["disk_format", "container_format", "path", "kind"]
+ copyin_props = ["disk_format", "container_format", "path", "kind", "tag"]
def get_xos_args(self):
args = super(XOSImage, self).get_xos_args()
diff --git a/xos/tosca/resources/networktemplate.py b/xos/tosca/resources/networktemplate.py
index 557964e..3a5ce59 100644
--- a/xos/tosca/resources/networktemplate.py
+++ b/xos/tosca/resources/networktemplate.py
@@ -12,7 +12,7 @@
class XOSNetworkTemplate(XOSResource):
provides = "tosca.nodes.NetworkTemplate"
xos_model = NetworkTemplate
- copyin_props = ["visibility", "translation", "shared_network_name", "shared_network_id", "toplogy_kind", "controller_kind"]
+ copyin_props = ["visibility", "translation", "shared_network_name", "shared_network_id", "toplogy_kind", "controller_kind", "access"]
def get_xos_args(self):
args = super(XOSNetworkTemplate, self).get_xos_args()
diff --git a/xos/tosca/resources/tenant.py b/xos/tosca/resources/tenant.py
new file mode 100644
index 0000000..831f6eb
--- /dev/null
+++ b/xos/tosca/resources/tenant.py
@@ -0,0 +1,60 @@
+import importlib
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+import pdb
+
+from ceilometer.models import Tenant, Service
+
+from xosresource import XOSResource
+
+class XOSTenant(XOSResource):
+ provides = "tosca.nodes.Tenant"
+ xos_model = Tenant
+ name_field = None
+ copyin_props = ("kind", "service_specific_attribute")
+
+ def get_xos_args(self, throw_exception=True):
+ args = super(XOSTenant, self).get_xos_args()
+
+ provider_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+ if provider_name:
+ args["provider_service"] = self.get_xos_object(Service, throw_exception=throw_exception, name=provider_name)
+
+ return args
+
+ def get_existing_objs(self):
+ args = self.get_xos_args(throw_exception=False)
+ provider_service = args.get("provider", None)
+ if provider_service:
+ return [ self.get_xos_object(provider_service=provider_service) ]
+ return []
+
+ def create(self):
+ model_class = self.get_property("model")
+ if model_class:
+ model_name = ".".join(model_class.split(".")[:-1])
+ class_name = model_class.split(".")[-1]
+ module = importlib.import_module(model_name)
+ xos_model = getattr(module, class_name)
+ else:
+ xos_model = self.xos_model
+
+ xos_args = self.get_xos_args()
+ xos_obj = xos_model(**xos_args)
+ xos_obj.caller = self.user
+ xos_obj.save()
+
+ self.info("Created %s '%s'" % (self.xos_model.__name__,str(xos_obj)))
+
+ self.postprocess(xos_obj)
+
+ def postprocess(self, obj):
+ pass
+
+ def can_delete(self, obj):
+ return super(XOSTenant, self).can_delete(obj)
+
diff --git a/xos/tosca/samples/helloworld-chain.yaml b/xos/tosca/samples/helloworld-chain.yaml
new file mode 100644
index 0000000..c72aa3d
--- /dev/null
+++ b/xos/tosca/samples/helloworld-chain.yaml
@@ -0,0 +1,68 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Two services "service_one" and "service_two" with a tenancy relationship.
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+
+ Private-Indirect:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ access: indirect
+
+ mysite:
+ type: tosca.nodes.Site
+
+ service_vcpe:
+ type: tosca.nodes.Service
+ requirements:
+ - helloworld_tenant:
+ node: service_helloworld
+ relationship: tosca.relationships.TenantOfService
+
+ service_helloworld:
+ type: tosca.nodes.Service
+ properties:
+ kind: helloworldservice_complete
+ view_url: /admin/helloworldservice_complete/helloworldservicecomplete/$id$/
+
+ tenant_helloworld:
+ type: tosca.nodes.Tenant
+ properties:
+ kind: helloworldservice_complete
+ service_specific_attribute: "{\"display_message\": \"Hello World from Tosca\"}"
+ model: helloworldservice_complete.models.HelloWorldTenantComplete
+ requirements:
+ - provider_service:
+ node: service_helloworld
+ relationship: tosca.relationships.MemberOfService
+
+
+ mysite_helloworld:
+ type: tosca.nodes.Slice
+ requirements:
+ - service:
+ node: service_helloworld
+ relationship: tosca.relationships.MemberOfService
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+
+ helloworld_access:
+ type: tosca.nodes.network.Network
+ properties:
+ ip_version: 4
+ requirements:
+ - network_template:
+ node: Private-Indirect
+ relationship: tosca.relationships.UsesNetworkTemplate
+ - owner:
+ node: mysite_helloworld
+ relationship: tosca.relationships.MemberOfSlice
+ - connection:
+ node: mysite_helloworld
+ relationship: tosca.relationships.ConnectsToSlice
+
diff --git a/xos/xos/config.py b/xos/xos/config.py
index ab78fa1..7a64de9 100644
--- a/xos/xos/config.py
+++ b/xos/xos/config.py
@@ -13,7 +13,7 @@
"""
XOS_DIR = "/opt/xos"
-DEFAULT_CONFIG_FN = os.path.join(XOS_DIR, "xos/xos_configuration/")
+DEFAULT_CONFIG_FN = os.path.join(XOS_DIR, "xos_configuration/")
# warning for now, remove once we're sure everyone has made the change
if (os.path.exists("/opt/planetstack/plstackapi_config") and (not os.path.exists(DEFAULT_CONFIG_FN))):
@@ -82,7 +82,7 @@
try:
if os.path.isdir(filename):
config_list = list(reversed(os.listdir(filename)))
- config_list = [DEFAULT_CONFIG_FN + s for s in config_list]
+ config_list = [os.path.join(filename, s) for s in config_list]
self.config.read(config_list)
else:
self.config.read(filename)
diff --git a/xos/xos_config b/xos/xos_config
deleted file mode 100644
index b86d618..0000000
--- a/xos/xos_config
+++ /dev/null
@@ -1,45 +0,0 @@
-[plc]
-name=plc
-deployment=plc
-
-[db]
-name=xos
-user=postgres
-password=password
-host=localhost
-port=5432
-
-[api]
-host=localhost
-port=8000
-ssl_key=None
-ssl_cert=None
-ca_ssl_cert=None
-ratelimit_enabled=0
-omf_enabled=0
-mail_support_address=support@localhost
-nova_enabled=True
-logfile=/var/log/xos.log
-
-[nova]
-admin_user=admin@domain.com
-admin_password=admin
-admin_tenant=admin
-url=http://localhost:5000/v2.0/
-default_image=None
-default_flavor=m1.small
-default_security_group=default
-ca_ssl_cert=/etc/ssl/certs/ca-certificates.crt
-
-[observer]
-pretend=False
-backoff_disabled=False
-images_directory=/opt/xos/images
-dependency_graph=/opt/xos/model-deps
-logfile=/var/log/xos_backend.log
-
-[gui]
-disable_minidashboard=True
-#branding_name=CORD
-#branding_css=/static/cord.css
-#branding_icon=/static/onos-logo.png
diff --git a/xos/xos/xos_configuration/xos_common_config b/xos/xos_configuration/xos_common_config
similarity index 100%
rename from xos/xos/xos_configuration/xos_common_config
rename to xos/xos_configuration/xos_common_config
diff --git a/xos/xos/xos_configuration/xos_frontend_config b/xos/xos_configuration/xos_frontend_config
similarity index 100%
rename from xos/xos/xos_configuration/xos_frontend_config
rename to xos/xos_configuration/xos_frontend_config