[Kimchi-devel] [PATCH 07/22] refactor model: Create a separated model for debug report resource
Aline Manera
alinefm at linux.vnet.ibm.com
Tue Jan 28 20:21:21 UTC 2014
From: Aline Manera <alinefm at br.ibm.com>
The model implementation for config and its sub-resources were added to
model_/debugreports.py
The idea is create a separated model implementation for each resource.
Signed-off-by: Aline Manera <alinefm at br.ibm.com>
---
src/kimchi/model_/debugreports.py | 167 +++++++++++++++++++++++++++++++++++++
src/kimchi/utils.py | 19 ++++-
2 files changed, 182 insertions(+), 4 deletions(-)
create mode 100644 src/kimchi/model_/debugreports.py
diff --git a/src/kimchi/model_/debugreports.py b/src/kimchi/model_/debugreports.py
new file mode 100644
index 0000000..39402aa
--- /dev/null
+++ b/src/kimchi/model_/debugreports.py
@@ -0,0 +1,167 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013
+#
+# Authors:
+# Aline Manera <alinefm at linux.vnet.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import fnmatch
+import glob
+import logging
+import os
+import shutil
+import subprocess
+import time
+
+from kimchi import config
+from kimchi.exception import NotFoundError, OperationFailed
+from kimchi.model_.tasks import TaskModel
+from kimchi.utils import add_task, kimchi_log
+
+
+class DebugReportsModel(object):
+ def __init__(self, **kargs):
+ self.objstore = kargs['objstore']
+ self.task = TaskModel(**kargs)
+
+ def create(self, params):
+ ident = params['name']
+ taskid = self._gen_debugreport_file(ident)
+ return self.task.lookup(taskid)
+
+ def get_list(self):
+ path = config.get_debugreports_path()
+ file_pattern = os.path.join(path, '*.*')
+ file_lists = glob.glob(file_pattern)
+ file_lists = [os.path.split(file)[1] for file in file_lists]
+ name_lists = [file.split('.', 1)[0] for file in file_lists]
+
+ return name_lists
+
+ def _gen_debugreport_file(self, name):
+ gen_cmd = self.get_system_report_tool()
+
+ if gen_cmd is not None:
+ return add_task('', gen_cmd, self.objstore, name)
+
+ raise OperationFailed("debugreport tool not found")
+
+ @staticmethod
+ def sosreport_generate(cb, name):
+ command = 'sosreport --batch --name "%s"' % name
+ try:
+ retcode = subprocess.call(command, shell=True,
+ stdout=subprocess.PIPE)
+ if retcode < 0:
+ raise OperationFailed('Command terminated with signal')
+ elif retcode > 0:
+ raise OperationFailed('Command failed: rc = %i' % retcode)
+ pattern = '/tmp/sosreport-%s-*' % name
+ for reportFile in glob.glob(pattern):
+ if not fnmatch.fnmatch(reportFile, '*.md5'):
+ output = reportFile
+ break
+ else:
+ # sosreport tends to change the name mangling rule and
+ # compression file format between different releases.
+ # It's possible to fail to match a report file even sosreport
+ # runs successfully. In future we might have a general name
+ # mangling function in kimchi to format the name before passing
+ # it to sosreport. Then we can delete this exception.
+ raise OperationFailed('Can not find generated debug report '
+ 'named by %s' % pattern)
+ ext = output.split('.', 1)[1]
+ path = config.get_debugreports_path()
+ target = os.path.join(path, name)
+ target_file = '%s.%s' % (target, ext)
+ shutil.move(output, target_file)
+ os.remove('%s.md5' % output)
+ cb('OK', True)
+
+ return
+
+ except OSError:
+ raise
+
+ except Exception, e:
+ # No need to call cb to update the task status here.
+ # The task object will catch the exception rasied here
+ # and update the task status there
+ log = logging.getLogger('Model')
+ log.warning('Exception in generating debug file: %s', e)
+ raise OperationFailed(e)
+
+ @staticmethod
+ def get_system_report_tool():
+ # Please add new possible debug report command here
+ # and implement the report generating function
+ # based on the new report command
+ report_tools = ({'cmd': 'sosreport --help',
+ 'fn': DebugReportsModel.sosreport_generate},)
+
+ # check if the command can be found by shell one by one
+ for helper_tool in report_tools:
+ try:
+ retcode = subprocess.call(helper_tool['cmd'], shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ if retcode == 0:
+ return helper_tool['fn']
+ except Exception, e:
+ kimchi_log.info('Exception running command: %s', e)
+
+ return None
+
+
+class DebugReportModel(object):
+ def __init__(self, **kargs):
+ pass
+
+ def lookup(self, name):
+ path = config.get_debugreports_path()
+ file_pattern = os.path.join(path, name)
+ file_pattern = file_pattern + '.*'
+ try:
+ file_target = glob.glob(file_pattern)[0]
+ except IndexError:
+ raise NotFoundError('no such report')
+
+ ctime = os.stat(file_target).st_ctime
+ ctime = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(ctime))
+ file_target = os.path.split(file_target)[-1]
+ file_target = os.path.join("/data/debugreports", file_target)
+ return {'file': file_target,
+ 'ctime': ctime}
+
+ def delete(self, name):
+ path = config.get_debugreports_path()
+ file_pattern = os.path.join(path, name + '.*')
+ try:
+ file_target = glob.glob(file_pattern)[0]
+ except IndexError:
+ raise NotFoundError('no such report')
+
+ os.remove(file_target)
+
+
+class DebugReportContentModel(object):
+ def __init__(self, **kargs):
+ self._debugreport = DebugReportModel()
+
+ def lookup(self, name):
+ return self._debugreport.lookup(name)
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index 59500dd..30c09d4 100644
--- a/src/kimchi/utils.py
+++ b/src/kimchi/utils.py
@@ -25,17 +25,28 @@ import cherrypy
import os
import subprocess
import urllib2
-
+from threading import Timer
from cherrypy.lib.reprconf import Parser
-from kimchi.exception import TimeoutExpired
-
from kimchi import config
-from threading import Timer
+from kimchi.asynctask import AsyncTask
kimchi_log = cherrypy.log.error_log
+task_id = 0
+
+
+def get_next_task_id():
+ global task_id
+ task_id += 1
+ return task_id
+
+
+def add_task(target_uri, fn, objstore, opaque=None):
+ id = get_next_task_id()
+ AsyncTask(id, target_uri, fn, objstore, opaque)
+ return id
def is_digit(value):
--
1.7.10.4
More information about the Kimchi-devel
mailing list