jenkins-bot has submitted this change and it was merged.

Change subject: Introduce Tool objects
......................................................................


Introduce Tool objects

- Fully encapsulate a valid tool
- Provide logging functionality

Change-Id: Ia6fd5fcfa606f759f0c152e5e02a8834430a0fc2
---
M destiny/collector.py
M destiny/manifest.py
M destiny/servicemonitor.py
A destiny/tool.py
4 files changed, 52 insertions(+), 31 deletions(-)

Approvals:
  Legoktm: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/destiny/collector.py b/destiny/collector.py
index e981818..bde1832 100644
--- a/destiny/collector.py
+++ b/destiny/collector.py
@@ -3,11 +3,9 @@
 import glob
 import yaml
 import logging
-import time
-import subprocess
-
 
 from .manifest import Manifest
+from .tool import Tool
 
 
 class ManifestCollector(object):
@@ -21,25 +19,6 @@
         handler.setFormatter(logging.Formatter('%(asctime)s %(message)s'))
         self.log.addHandler(handler)
         self.log.setLevel(logging.DEBUG)
-
-    def toollog(self, toolname, message):
-        """
-        Write to a log file in the tool's homedir
-        :param toolname: validated tool name on whose homedir to write log in
-        """
-        # use ugly sudo and whatnot here instead of 'proper' file stuff 
because unsure how to
-        # preserve permissions in atomic way when writing to a file that may 
not exist already
-        log_line = "%s %s" % (time.asctime(), message)
-        log_path = '/data/project/%s/services.log' % toolname
-        # Ensure that the file exists already and is owned appropriately by 
the tool
-        subprocess.check_output([
-            '/usr/bin/sudo',
-            '-i', '-u', 'tools.%s' % toolname,
-            '/usr/bin/touch', log_path
-        ])
-        with open(log_path, 'a') as f:
-            f.write(log_line)
-            self.log.info('[%s] %s', toolname, message)
 
     def collect(self):
         """
@@ -63,7 +42,8 @@
                     continue
 
             with open(manifest_file) as f:
-                manifest = Manifest(toolname, yaml.safe_load(f))
+                tool = Tool.from_name(toolname)
+                manifest = Manifest(tool, yaml.safe_load(f))
                 manifests.append(manifest)
         self.manifests = manifests
         self.log.info("Collected %s manifests", len(self.manifests))
diff --git a/destiny/manifest.py b/destiny/manifest.py
index e8a8789..83a834a 100644
--- a/destiny/manifest.py
+++ b/destiny/manifest.py
@@ -8,13 +8,13 @@
     class InvalidManifestException(Exception):
         pass
 
-    def __init__(self, toolname, data):
+    def __init__(self, tool, data):
         """
         Constructs a manifest object from manifest data.
 
         It will ignore extra keys, but throw exceptions on invalid values.
 
-        :param toolname: str Name of tool for which this is the manifest
+        :param tool: tools.Tool Tool object representing the tool this is a 
manifest for
         :param data: dict containing manifest structure. Currently supported 
keys are:
                      web: Type of webservice to run for this tool. Currently 
supported
                           values are lighttpd, lighttpd-precise, nodejs, 
uwsgi-python, tomcat
@@ -22,7 +22,7 @@
         if data is None:
             data = {}  # Handle empty service manifests
         self.data = data
-        self.toolname = toolname
+        self.tool = tool
 
         if 'web' in data and data['web'] not in Manifest.WEBSERVICE_TYPES:
             raise Manifest.InvalidManifestException('webservice type should be 
one of %s', Manifest.WEBSERVICE_TYPES)
@@ -47,6 +47,6 @@
     def __str__(self):
         # Because yaml always does stupid ordering, and we wouldn't want that 
would we
         return "tool: %s\n%s" % (
-            self.toolname,
+            self.tool.name,
             yaml.dump({'manifest': self.data}, default_flow_style=False)
         )
diff --git a/destiny/servicemonitor.py b/destiny/servicemonitor.py
index 27d1484..f58fa1a 100644
--- a/destiny/servicemonitor.py
+++ b/destiny/servicemonitor.py
@@ -7,13 +7,13 @@
 
 class ServiceMonitor(ManifestCollector):
     def _webjob_name(self, manifest):
-        return '%s-%s' % (manifest.webservice_server, manifest.toolname)
+        return '%s-%s' % (manifest.webservice_server, manifest.tool.name)
 
     def _start_webservice(self, manifest):
-        self.log.info('Starting webservice for tool %s', manifest.toolname)
+        self.log.info('Starting webservice for tool %s', manifest.tool.name)
         return subprocess.check_output([
             '/usr/bin/sudo',
-            '-i', '-u', 'tools.%s' % manifest.toolname,
+            '-i', '-u', manifest.tool.username,
             '/usr/local/bin/webservice',
             '--release', manifest.webservice_release,
             manifest.webservice_server,
@@ -29,7 +29,8 @@
             job = qstat_xml.find('.//job_list[JB_name="%s"]' % 
self._webjob_name(manifest))
             if job is None or 'r' not in job.findtext('.//state'):
                 self._start_webservice(manifest)
-                self.toollog(manifest.toolname, 'No running webservice job 
found, starting it')
+                manifest.tool.log('No running webservice job found, starting 
it')
+                self.log.info('Started webservice for %s', manifest.tool.name)
                 restarts_count += 1
         self.log.info('Service monitor run completed, %s webservices 
restarted', restarts_count)
 
diff --git a/destiny/tool.py b/destiny/tool.py
new file mode 100644
index 0000000..979eebc
--- /dev/null
+++ b/destiny/tool.py
@@ -0,0 +1,40 @@
+import os
+import time
+import pwd
+import subprocess
+
+
+class Tool(object):
+    USER_NAME_PATTERN = 'tools.%s'
+
+    def __init__(self, name, username, uid, home):
+        self.name = name
+        self.uid = uid
+        self.username = username
+        self.home = home
+
+    @classmethod
+    def from_name(cls, name):
+        """
+        Create a Tool instance from a tool name
+        """
+        username = Tool.USER_NAME_PATTERN % (name, )
+        user_info = pwd.getpwnam(username)
+        return cls(name, user_info.pw_name, user_info.pw_uid, user_info.pw_dir)
+
+    def log(self, message):
+        """
+        Write to a log file in the tool's homedir
+        """
+        # use ugly sudo and whatnot here instead of 'proper' file stuff 
because unsure how to
+        # preserve permissions in atomic way when writing to a file that may 
not exist already
+        log_line = "%s %s" % (time.asctime(), message)
+        log_path = os.path.join(self.home, 'services.log')
+        # Ensure that the file exists already and is owned appropriately by 
the tool
+        subprocess.check_output([
+            '/usr/bin/sudo',
+            '-i', '-u', self.username,
+            '/usr/bin/touch', log_path
+        ])
+        with open(log_path, 'a') as f:
+            f.write(log_line)

-- 
To view, visit https://gerrit.wikimedia.org/r/202293
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ia6fd5fcfa606f759f0c152e5e02a8834430a0fc2
Gerrit-PatchSet: 4
Gerrit-Project: operations/software/tools-manifest
Gerrit-Branch: master
Gerrit-Owner: Yuvipanda <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Tim Landscheidt <[email protected]>
Gerrit-Reviewer: coren <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to