Base net-virt CLI files on top of which ONOS specific changes will be done
diff --git a/cli/sdncon/apps/cstats/__init__.py b/cli/sdncon/apps/cstats/__init__.py
new file mode 100755
index 0000000..9ab2783
--- /dev/null
+++ b/cli/sdncon/apps/cstats/__init__.py
@@ -0,0 +1,16 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
diff --git a/cli/sdncon/apps/cstats/models.py b/cli/sdncon/apps/cstats/models.py
new file mode 100755
index 0000000..f644f71
--- /dev/null
+++ b/cli/sdncon/apps/cstats/models.py
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+from django.db import models
+
+# Create your models here.
diff --git a/cli/sdncon/apps/cstats/static/css/timeselector.css b/cli/sdncon/apps/cstats/static/css/timeselector.css
new file mode 100755
index 0000000..223ee4e
--- /dev/null
+++ b/cli/sdncon/apps/cstats/static/css/timeselector.css
@@ -0,0 +1,122 @@
+ ul.bsntimeinterval {
+ list-style: none;
+ margin: 2px;
+ padding: 0px;
+ vertical-align: middle;
+ clear: both;
+ }
+ ul.bsntimeinterval li {
+ float: left;
+ margin: 0;
+ padding: 0;
+ height: 30px;
+ display: table;
+ border-spacing: 0px;
+ }
+ .bsntimeinterval div.center {
+ display: table-cell;
+ vertical-align: middle;
+ }
+ .bsntimeinterval a {
+ display: block;
+ }
+ a.bsnselector {
+ cursor: pointer;
+ margin: 0px;
+ padding: 3px;
+ border: solid 1px #333333;
+ border-right: none;
+ color: #2E6E9E;
+ vertical-align: middle;
+
+ background-color: #EEEEEE;
+ /* Firefox 3.6+ */
+ background: -moz-linear-gradient(100% 100% 90deg, #CCCCCC, #EEEEEE);
+
+ /* Safari 5.1+, Chrome 10+ */
+ background: -webkit-linear-gradient(#EEEEEE, #CCCCCC);
+
+ /* Opera 11.10+ */
+ background: -o-linear-gradient(#CCCCCC, #EEEEEE);
+
+ }
+ a.bsnselector.left {
+ border-top-left-radius: .5em;
+ border-bottom-left-radius: .5em;
+ }
+ a.bsnselector.right {
+ border-top-right-radius: .5em;
+ border-bottom-right-radius: .5em;
+ border-right: solid 1px #333333;
+ }
+ a.bsnselector:hover {
+ background-color: #DDDDDD;
+
+ /* Firefox 3.6+ */
+ background: -moz-linear-gradient(100% 100% 90deg, #BBBBBB, #DDDDDD);
+
+ /* Safari 5.1+, Chrome 10+ */
+ background: -webkit-linear-gradient(#DDDDDD, #BBBBBB);
+
+ /* Opera 11.10+ */
+ background: -o-linear-gradient(#BBBBBB, #DDDDDD);
+ }
+ a.bsnselector.selected {
+ color: #EEEEEE;
+ background-color: #2E6E9E;
+
+ /* Firefox 3.6+ */
+ background: -moz-linear-gradient(100% 100% 90deg, #2E6E9E, #3D92C2);
+
+ /* Safari 5.1+, Chrome 10+ */
+ background: -webkit-linear-gradient(#3D92C2, #2E6E9E);
+
+ /* Opera 11.10+ */
+ background: -o-linear-gradient(#2E6E9E, #3D92C2);
+ }
+ .bsnlabel {
+ margin-left: 5px;
+ margin-right: 2px;
+ }
+ .bsnlabel.disabled {
+ color: #BBBBBB;
+ }
+ .bsntimepicker {
+ width: 10em;
+ }
+ .bsncheckbox {
+ vertical-align: middle;
+ margin-left: 5px;
+ margin-right: 0px;
+ }
+ .bsnarrow {
+ cursor: pointer;
+ padding-left: 3px;
+ padding-right: 3px;
+ }
+ .bsnarrow div {
+ width: 0;
+ height: 0;
+ }
+ .bsnarrow.left div {
+ border-top: 11px solid transparent;
+ border-bottom: 11px solid transparent;
+ border-right:10px solid #CCCCCC;
+ }
+ .bsnarrow.left:hover div {
+ border-right:10px solid #2E6E9E;
+ }
+ .bsnarrow.right div {
+ border-top: 11px solid transparent;
+ border-bottom: 11px solid transparent;
+ border-left: 10px solid #CCCCCC;
+ }
+ .bsnarrow.right:hover div {
+ border-left: 10px solid #2E6E9E;
+ }
+ .bsncheckbox {
+ display: inline;
+ }
+ .clear {
+ clear: both;
+ }
\ No newline at end of file
diff --git a/cli/sdncon/apps/cstats/tests.py b/cli/sdncon/apps/cstats/tests.py
new file mode 100755
index 0000000..793e610
--- /dev/null
+++ b/cli/sdncon/apps/cstats/tests.py
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/cli/sdncon/apps/cstats/urls.py b/cli/sdncon/apps/cstats/urls.py
new file mode 100755
index 0000000..175841f
--- /dev/null
+++ b/cli/sdncon/apps/cstats/urls.py
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+from django.conf.urls.defaults import *
+import os
+
+# Add the URLs that you need here e.g.:
+
+urlpatterns = patterns('',
+# (r'^tab_mytab/', 'views.mytab'),
+)
+
+# Uncomment this if you have bundeled in static resources (e.g. javascript) or images
+# They will be served from:
+# app-name/static
+# app-name/img
+
+urlpatterns += patterns('',
+ (r'^static/(?P<path>.*)$', 'django.views.static.serve', \
+ {'document_root': os.path.join(os.path.dirname(__file__),'static')}),
+# (r'^img/(?P<path>.*)$', 'django.views.static.serve', \
+# {'document_root': os.path.join(os.path.dirname(__file__),'img')}),
+)
+
diff --git a/cli/sdncon/apps/cstats/views.py b/cli/sdncon/apps/cstats/views.py
new file mode 100755
index 0000000..eef38dd
--- /dev/null
+++ b/cli/sdncon/apps/cstats/views.py
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+# Views for the application
+#
+
+from django.shortcuts import render_to_response
+from sdncon.apploader import AppLoader, AppLister
+from sdncon.controller.models import Switch
+import os
+
+def bsc_app_init():
+ # By default, App Name is the same as directory name. Change if needed.
+ APP_NAME = os.path.dirname(__file__).split("/")[-1]
+
+ # Create the App. Parameters are
+ # - Name: the id, lowercase letters only
+ # - Label: Human readable discription for the menu to the left
+ # - Priority: determines ranking the menu to the left), One-line description
+ # - Description: One line description of the app
+ app = AppLister(APP_NAME, "Controller Stats", 5, "Controller Stats")
+
+ # Add Tabs. Parameters are:
+ # - Name: the id, lowercase letters only
+ # - Label: Human readable discription for the menu to the left
+ # - View: name of the python function that contains the django view (see below)
+ app.addTab("openflow_graphs", "OpenFlow Graphs", flow_graphs_view)
+ app.addTab("system_graphs", "System Graphs", system_stats_graph_view)
+ AppLoader.addApp(app)
+
+def system_stats_graph_view(request):
+ return render_to_response('apps/cstats/templates/graphs.html', {} )
+
+def flow_graphs_view(request):
+ return render_to_response('apps/cstats/templates/openflowgraphs.html', {} )
+
diff --git a/cli/sdncon/apps/docs/__init__.py b/cli/sdncon/apps/docs/__init__.py
new file mode 100755
index 0000000..9ab2783
--- /dev/null
+++ b/cli/sdncon/apps/docs/__init__.py
@@ -0,0 +1,16 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
diff --git a/cli/sdncon/apps/docs/static/pdf/user-guide.pdf b/cli/sdncon/apps/docs/static/pdf/user-guide.pdf
new file mode 100755
index 0000000..af8b537
--- /dev/null
+++ b/cli/sdncon/apps/docs/static/pdf/user-guide.pdf
Binary files differ
diff --git a/cli/sdncon/apps/docs/urls.py b/cli/sdncon/apps/docs/urls.py
new file mode 100755
index 0000000..f345d5f
--- /dev/null
+++ b/cli/sdncon/apps/docs/urls.py
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+from django.conf.urls.defaults import *
+import os
+
+urlpatterns = patterns('docs.views',
+ (r'^user-guide/?$', 'user_guide'),
+)
+
diff --git a/cli/sdncon/apps/docs/views.py b/cli/sdncon/apps/docs/views.py
new file mode 100755
index 0000000..6276736
--- /dev/null
+++ b/cli/sdncon/apps/docs/views.py
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+# Views for the application
+#
+
+import os
+from django.shortcuts import render_to_response
+from sdncon.apploader import AppLoader, AppLister
+from sdncon.clusterAdmin.utils import isCloudBuild
+
+docs_enabled = False
+
+def bsc_app_init():
+ if not docs_enabled:
+ return
+
+ APP_NAME = os.path.dirname(__file__).split("/")[-1]
+ app = AppLister(APP_NAME, "Documentation", 9, "User Guide")
+ app.addTab("docs", "User Guide", user_guide)
+ AppLoader.addApp(app)
+
+def user_guide(request):
+ url = '/docs/static/pdf/user-guide.pdf'
+ return render_to_response('apps/docs/templates/pdf_doc.html', {'url' : url})
diff --git a/cli/sdncon/apps/logs/__init__.py b/cli/sdncon/apps/logs/__init__.py
new file mode 100755
index 0000000..9ab2783
--- /dev/null
+++ b/cli/sdncon/apps/logs/__init__.py
@@ -0,0 +1,16 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
diff --git a/cli/sdncon/apps/logs/models.py b/cli/sdncon/apps/logs/models.py
new file mode 100755
index 0000000..f644f71
--- /dev/null
+++ b/cli/sdncon/apps/logs/models.py
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+from django.db import models
+
+# Create your models here.
diff --git a/cli/sdncon/apps/logs/tests.py b/cli/sdncon/apps/logs/tests.py
new file mode 100755
index 0000000..793e610
--- /dev/null
+++ b/cli/sdncon/apps/logs/tests.py
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/cli/sdncon/apps/logs/urls.py b/cli/sdncon/apps/logs/urls.py
new file mode 100755
index 0000000..0ba1f5f
--- /dev/null
+++ b/cli/sdncon/apps/logs/urls.py
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+from django.conf.urls.defaults import *
+import os
+
+# Add the URLs that you need here e.g.:
+
+urlpatterns = patterns('',
+# (r'^tab_mytab/', 'views.mytab'),
+)
+
+# Uncomment this if you have bundeled in static resources (e.g. javascript) or images
+# They will be served from:
+# app-name/static
+# app-name/img
+
+urlpatterns += patterns('',
+ (r'^static/(?P<path>.*)$', 'django.views.static.serve', \
+ {'document_root': os.path.join(os.path.dirname(__file__),'static')}),
+# (r'^img/(?P<path>.*)$', 'django.views.static.serve', \
+# {'document_root': os.path.join(os.path.dirname(__file__),'img')}),
+)
+
+urlpatterns += patterns('logs.views',
+(r'^rest/v1/controller-log-data-all/(?P<cluster>[A-Za-z0-9_:.\-]+)/(?P<controller>[A-Za-z0-9_\.\-]+)/?$', 'controller_log_data_all'),
+(r'^rest/v1/controller-log-data-controller/(?P<cluster>[A-Za-z0-9_:.\-]+)/(?P<controller>[A-Za-z0-9_\.\-]+)/?$', 'controller_log_data_controller'),
+(r'^rest/v1/controller-log-data-db/(?P<cluster>[A-Za-z0-9_:.\-]+)/(?P<controller>[A-Za-z0-9_\.\-]+)/?$', 'controller_log_data_db'),
+(r'^rest/v1/controller-log-data-sdncon/(?P<cluster>[A-Za-z0-9_:.\-]+)/(?P<controller>[A-Za-z0-9_\.\-]+)/?$', 'controller_log_data_sdncon'),
+)
+
diff --git a/cli/sdncon/apps/logs/views.py b/cli/sdncon/apps/logs/views.py
new file mode 100755
index 0000000..4018f90
--- /dev/null
+++ b/cli/sdncon/apps/logs/views.py
@@ -0,0 +1,231 @@
+#
+# Copyright (c) 2013 Big Switch Networks, Inc.
+#
+# Licensed under the Eclipse Public License, Version 1.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+
+# Views for the application
+#
+
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.utils import simplejson
+from sdncon.rest.jsonview import JsonResponse
+from sdncon.apploader import AppLoader, AppLister
+from sdncon.stats.views import init_db_connection
+from sdncon.stats.data import get_log_event_data
+import os
+import time
+import sdncon
+
+ComponentXlation = {
+ 'cassandra': 'database',
+ 'sdncon': 'sdncon',
+ 'sdnplatform': 'controller'
+}
+
+def log_collection_enabled(config_file="%s/statd/statd.conf" % sdncon.SDN_ROOT):
+ import json
+ enabled = False
+ try:
+ with open(config_file, 'r') as fp:
+ conf = json.load(fp)
+ if conf.get('input'):
+ for i in conf['input']:
+ if i.get('name') == 'LogCollector' and i.get('modules'):
+ enabled = True
+ break;
+ except:
+ pass
+ return enabled
+
+def bsc_app_init():
+ # Check if logging is enabled, else do not start the app
+ if not log_collection_enabled():
+ return
+
+ # By default, App Name is the same as directory name. Change if needed.
+ APP_NAME = os.path.dirname(__file__).split("/")[-1]
+
+ # Create the App. Parameters are
+ # - Name: the id, lowercase letters only
+ # - Label: Human readable discription for the menu to the left
+ # - Priority: determines ranking the menu to the left), One-line description
+ # - Description: One line description of the app
+ app = AppLister(APP_NAME, "Logs", 5, "Controller Logs")
+
+ # Add Tabs. Parameters are:
+ # - Name: the id, lowercase letters only
+ # - Label: Human readable discription for the menu to the left
+ # - View: name of the python function that contains the django view (see below)
+ app.addTab("controllerlogs", "Controller Logs", controller)
+ app.addTab("dblogs", "Database Logs", db)
+ app.addTab("sdnconlogs", "SDNCon Logs", sdncon)
+ app.addTab("alllogs", "All Logs", all)
+ AppLoader.addApp(app)
+
+# Views - functions that serve the HTML that goes into each tab
+def controller(request):
+ return render_to_response('apps/logs/templates/logs.html', { 'source' : 'controller' } )
+
+def db(request):
+ return render_to_response('apps/logs/templates/logs.html', { 'source' : 'db' } )
+
+def sdncon(request):
+ return render_to_response('apps/logs/templates/logs.html', { 'source' : 'sdncon' } )
+
+def all(request):
+ return render_to_response('apps/logs/templates/logs.html', { 'source' : 'all' } )
+
+# Views defined in urls.py
+def controller_log_data_all(request, cluster, controller):
+ init_db_connection()
+ time_now = time.time()*1000 #conver to ms
+ # we only get one day for now, this will be fixed when we move to an actually scalable solution
+ data_dict = get_log_event_data(cluster, controller, time_now - 86400000, time_now)
+ arr = get_array_from_dict(data_dict, True)
+ return generic_server_side_datatable(request, arr)
+
+def controller_log_data_controller(request, cluster, controller):
+ init_db_connection()
+ time_now = time.time()*1000 #conver to ms
+ # we only get one day for now, this will be fixed when we move to an actually scalable solution
+ data_dict = get_log_event_data(cluster, controller, time_now - 86400000, time_now)
+ filtered_dict = []
+ for e in data_dict:
+ if e['component'] == 'sdnplatform' or e['component'] == 'sdnplatform.request':
+ filtered_dict.append(e)
+ arr = get_array_from_dict(filtered_dict, False)
+ return generic_server_side_datatable(request, arr)
+
+def controller_log_data_db(request, cluster, controller):
+ init_db_connection()
+ time_now = time.time()*1000 #conver to ms
+ # we only get one day for now, this will be fixed when we move to an actually scalable solution
+ data_dict = get_log_event_data(cluster, controller, time_now - 86400000, time_now)
+ filtered_dict = []
+ for e in data_dict:
+ if e['component'] == 'cassandra':
+ filtered_dict.append(e)
+ arr = get_array_from_dict(filtered_dict, False)
+ return generic_server_side_datatable(request, arr)
+
+def controller_log_data_sdncon(request, cluster, controller):
+ init_db_connection()
+ time_now = time.time()*1000 #conver to ms
+ # we only get one day for now, this will be fixed when we move to an actually scalable solution
+ data_dict = get_log_event_data(cluster, controller, time_now - 86400000, time_now)
+ filtered_dict = []
+ for e in data_dict:
+ if e['component'] == 'sdncon':
+ filtered_dict.append(e)
+ arr = get_array_from_dict(filtered_dict, False)
+ return generic_server_side_datatable(request, arr)
+
+
+# Helper functions
+def generic_server_side_datatable(request, data_array):
+ start = request.GET.get("iDisplayStart",0)
+ length = request.GET.get("iDisplayLength",10)
+ search_str = request.GET.get("sSearch",None)
+
+ if search_str:
+ data_array_f = []
+ for d in data_array:
+ for e in d:
+ try:
+ if e.find(search_str) > -1:
+ data_array_f.append(d)
+ break
+ except Exception:
+ pass
+ else:
+ data_array_f = data_array
+
+ data_subset = data_array_f[int(start):int(start)+int(length)]
+ response_data = '{ "aaData":'+simplejson.dumps(data_subset) + ', "iTotalDisplayRecords": ' + str(len(data_array_f)) + ', "iTotalRecords": ' + str(len(data_array_f)) +'}'
+ return HttpResponse(response_data, 'application/json')
+
+# Takes a dictionary that includes
+# { "timestamp": unix_ts, "level" : "string", "message": "msg" }
+# and turns it into a 2D array that includes
+# [ [unix_ts, level, message], [etc], [etc] ]
+def get_array_from_dict(dict, includeComp):
+ array = []
+ for element in reversed(dict):
+ if 'component' in element and element['component'] == 'sdnplatform.request':
+ entry = parse_sdnplatform_request_log_entry(element)
+ else:
+ entry = []
+ if 'timestamp' in element:
+ entry.append(element['timestamp'])
+ else:
+ entry.append('-')
+ if 'log-level' in element:
+ entry.append(element['log-level'])
+ else:
+ entry.append('-')
+ if 'message' in element:
+ entry.append(element['message'])
+ else:
+ entry.append('-')
+
+ if includeComp:
+ if 'component' in element:
+ entry.insert(1, ComponentXlation[element['component']])
+ else:
+ entry.append(1, '-')
+
+ array.append(entry)
+ return array
+
+# Parses a SDNPlatform request log entry into an array
+# Format is similar to
+# {
+# 'package': 'Python-urllib/2.7',
+# 'timestamp': 1306967011000L,
+# 'component': 'sdnplatform.request',
+# 'request': 'GET /wm/core/counter/00:00:00:00:00:73:28:02_OFPacketIn_L3_IPv4/json HTTP/1.1',
+# 'responseLen': '37',
+# 'client': '127.0.0.1',
+# 'responseCode': '200'
+# }
+# Output array is [unix_ts, level, message]
+def parse_sdnplatform_request_log_entry(element):
+ entry = []
+ if 'timestamp' in element:
+ entry.append(element['timestamp'])
+ else:
+ entry.append('-')
+ if 'responseCode' in element:
+ rc = element['responseCode']
+ if rc == '404' or rc == '500':
+ entry.append('ERROR')
+ elif rc == '200':
+ entry.append('INFO')
+ else:
+ entry.append('-')
+ else:
+ entry.append('-')
+ msg = ''
+ if 'request' in element:
+ msg += element['request']
+ if 'client' in element:
+ msg += ' CLIENT ' + element['client']
+ if 'responseCode' in element:
+ msg += ' ' + element['responseCode']
+ if 'package' in element:
+ msg += ' ' + element['package']
+ entry.append(msg)
+ return entry
+