blob: 992757eda44c2e240571d01dfa96e9a9db3c02ad [file] [log] [blame]
Joshua Hesketh0ddd6382013-07-26 10:33:36 +10001# Copyright ....
2
3import git
4import logging
5import os
6import select
7import subprocess
8import time
9
10
11class GitRepository(object):
12
13 """ Manage a git repository for our uses """
14 log = logging.getLogger("rcbau-ci.GitRepository")
15
16 def __init__(self, remote_url, local_path):
17 self.remote_url = remote_url
18 self.local_path = local_path
19 self._ensure_cloned()
20
21 self.repo = git.Repo(self.local_path)
22
23 def fetch(self, ref):
24 # The git.remote.fetch method may read in git progress info and
25 # interpret it improperly causing an AssertionError. Because the
26 # data was fetched properly subsequent fetches don't seem to fail.
27 # So try again if an AssertionError is caught.
28 origin = self.repo.remotes.origin
29 self.log.debug("Fetching %s from %s" % (ref, origin))
30
31 try:
32 origin.fetch(ref)
33 except AssertionError:
34 origin.fetch(ref)
35
36 def checkout(self, ref):
37 self.log.debug("Checking out %s" % ref)
38 return self.repo.git.checkout(ref)
39
40 def _ensure_cloned(self):
41 if not os.path.exists(self.local_path):
42 self.log.debug("Cloning from %s to %s" % (self.remote_url,
43 self.local_path))
44 git.Repo.clone_from(self.remote_url, self.local_path)
45
46 """ ####UNUSED>....
47 def _make_ssh_wrappesubprocessr(self, key):
48 name = os.path.join(self.config['git_working_dir'], '.ssh_wrapper')
49 fd = open(name, 'w')
50 fd.write('#!/bin/bash\n')
51 fd.write('ssh -i %s $@\n' % key)
52 fd.close()
53 os.chmod(name, 0755)
54 os.environ['GIT_SSH'] = name
55
56 def construct_git_url(self, project_name):
57 url = 'ssh://%s@%s:%s/%s' % (
58 self.config['gerrit_server']['user'],
59 self.config['gerrit_server']['host'],
60 self.config['gerrit_server']['port'],
61 project_name
62 )
63 url = 'https://%s/%s' % (
64 self.config['gerrit_server']['host'],
65 project_name
66 )
67 return url
68 """
69
70
71def execute_to_log(cmd, logfile, timeout=-1,
72 watch_logs=[
73 ('[syslog]', '/var/log/syslog'),
74 ('[sqlslo]', '/var/log/mysql/slow-queries.log'),
75 ('[sqlerr]', '/var/log/mysql/error.log')
76 ],
77 heartbeat=True
78 ):
79 """ Executes a command and logs the STDOUT/STDERR and output of any
80 supplied watch_logs from logs into a new logfile
81
82 watch_logs is a list of tuples with (name,file) """
83
84 if not os.path.isdir(os.path.dirname(logfile)):
85 os.makedirs(os.path.dirname(logfile))
86
87 logger = logging.getLogger('execute_to_log')
88 log_hanlder = logging.FileHandler(logfile)
89 log_formatter = logging.Formatter('%(asctime)s %(message)s')
90 log_hanlder.setFormatter(log_formatter)
91 logger.addHandler(log_hanlder)
92
93 descriptors = {}
94
95 for watch_file in watch_logs:
96 fd = os.open(watch_file[1], os.O_RDONLY)
97 os.lseek(fd, 0, os.SEEK_END)
98 descriptors[fd] = dict(
99 name=watch_file[0],
100 poll=select.POLLIN
101 )
102
103 cmd += ' 2>&1'
104 start_time = time.time()
105 p = subprocess.Popen(
106 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
107
108 descriptors[p.stdout.fileno()] = dict(
109 name='[stdout]',
110 poll=(select.POLLIN | select.POLLHUP)
111 )
112 descriptors[p.stderr.fileno()] = dict(
113 name='[stderr]',
114 poll=(select.POLLIN | select.POLLHUP)
115 )
116
117 poll_obj = select.poll()
118 for fd, descriptor in descriptors.items():
119 poll_obj.register(fd, descriptor['poll'])
120
121 last_heartbeat = time.time()
122
123 while p.poll() is None:
124 if timeout > 0 and time.time() - start_time > timeout:
125 # Append to logfile
126 logger.info("[timeout]")
127 os.kill(p.pid, 9)
128
129 for fd, flag in poll_obj.poll(0):
130 lines = os.read(fd, 1024 * 1024)
131 for l in lines.split('\n'):
132 if len(l) > 0:
133 l = '%s %s' % (descriptors[fd]['name'], l)
134 logger.info(l)
135 last_heartbeat = time.time()
136
137 if time.time() - last_heartbeat > 30:
138 # Append to logfile
139 logger.info("[heartbeat]")
140 last_heartbeat = time.time()
141
142 logger.info('[script exit code = %d]' % p.returncode)