PageRenderTime 92ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 1ms

/docs/hudson/OMERO-qa-upgrade.py

https://github.com/ximenesuk/openmicroscopy
Python | 390 lines | 371 code | 9 blank | 10 comment | 7 complexity | 3ce84fe433001bf08063eb1dda9c9e83 MD5 | raw file
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import os
  4. import platform
  5. import subprocess
  6. def DEFINE(key, value):
  7. m = globals()
  8. m[key] = os.environ.get(key, value)
  9. print key, "=>", m[key]
  10. ###########################################################################
  11. # DETECTION
  12. ###########################################################################
  13. WINDOWS = platform.system() == "Windows"
  14. p = subprocess.Popen(["hostname"], stdout=subprocess.PIPE)
  15. h = p.communicate()[0].strip()
  16. DEFINE("HOSTNAME", h)
  17. ###########################################################################
  18. # CONFIGURATION
  19. ###########################################################################
  20. # Most likely to be changed
  21. DEFINE("NAME", HOSTNAME)
  22. if HOSTNAME == "gretzky":
  23. DEFINE("ADDRESS", "gretzky.openmicroscopy.org.uk")
  24. elif HOSTNAME == "howe":
  25. DEFINE("ADDRESS", "howe.openmicroscopy.org.uk")
  26. elif HOSTNAME == "ome-dev-svr":
  27. DEFINE("NAME", "win-2k8")
  28. DEFINE("ADDRESS", "bp.openmicroscopy.org.uk")
  29. else:
  30. DEFINE("ADDRESS", HOSTNAME)
  31. # Don't send emails if we're not on a known host.
  32. DEFINE("SKIPEMAIL", "true")
  33. if "SKIPEMAIL" not in globals():
  34. DEFINE("SKIPEMAIL", "false")
  35. if WINDOWS:
  36. DEFINE("UNZIP", "C:\\Program Files (x86)\\7-Zip\\7z.exe")
  37. DEFINE("UNZIPARGS", "x")
  38. else:
  39. DEFINE("UNZIP", "unzip")
  40. DEFINE("UNZIPARGS", "")
  41. # new_server.py
  42. DEFINE("MEM", "Xmx1024M")
  43. DEFINE("SYM", "OMERO-CURRENT")
  44. DEFINE("CFG", os.path.join(os.path.expanduser("~"), "config.xml"))
  45. DEFINE("WEB", """'[["localhost", 4064, "%s"], ["gretzky.openmicroscopy.org.uk", 4064, "gretzky"], ["howe.openmicroscopy.org.uk", 4064, "howe"]]'""" % NAME)
  46. # send_email.py
  47. DEFINE("SUBJECT", "OMERO - %s was upgraded" % NAME)
  48. DEFINE("BRANCH", "OMERO-trunk")
  49. DEFINE("BUILD", "http://hudson.openmicroscopy.org.uk/job/%s/lastSuccessfulBuild/" % BRANCH)
  50. DEFINE("SENDER", "Chris Allan <callan@lifesci.dundee.ac.uk>")
  51. DEFINE("RECIPIENTS", ["ome-nitpick@lists.openmicroscopy.org.uk"])
  52. DEFINE("SERVER", "%s (%s)" % (NAME, ADDRESS))
  53. DEFINE("SMTP_SERVER", "smtp.dundee.ac.uk")
  54. DEFINE("WEBURL", "http://%s/omero/webclient/" % ADDRESS)
  55. DEFINE("SKIPWEB", "false")
  56. DEFINE("SKIPUNZIP", "false")
  57. ###########################################################################
  58. import fileinput
  59. import smtplib
  60. import sys
  61. import urllib
  62. import re
  63. from email.MIMEMultipart import MIMEMultipart
  64. from email.MIMEText import MIMEText
  65. from email.MIMEImage import MIMEImage
  66. from zipfile import ZipFile
  67. from xml.etree.ElementTree import XML, ElementTree, tostring
  68. class Artifacts(object):
  69. def __init__(self, build = BUILD):
  70. self.server = None
  71. self.win = list()
  72. self.mac = list()
  73. self.linux = list()
  74. url = urllib.urlopen(build+"api/xml")
  75. hudson_xml = url.read()
  76. url.close()
  77. root = XML(hudson_xml)
  78. artifacts = root.findall("./artifact")
  79. base_url = build+"artifact/"
  80. if len(artifacts) <= 0:
  81. raise AttributeError("No artifacts, please check build on Hudson.")
  82. for artifact in artifacts:
  83. filename = artifact.find("fileName").text
  84. if filename.startswith("OMERO.server"):
  85. self.server = base_url + artifact.find("relativePath").text
  86. elif filename.startswith('OMERO.source'):
  87. self.source = base_url + artifact.find("relativePath").text
  88. elif filename.startswith('OMERO.imagej') or\
  89. filename.startswith('OMERO.java') or\
  90. filename.startswith('OMERO.matlab') or\
  91. filename.startswith('OMERO.py') or\
  92. filename.startswith('OMERO.server'):
  93. pass
  94. elif filename.startswith("OMERO.importer"):
  95. regex = re.compile(r'.*win.zip')
  96. regex2 = re.compile(r'.*mac.zip')
  97. if not regex.match(filename) and not regex2.match(filename):
  98. self.linux.append(base_url + artifact.find("relativePath").text)
  99. else:
  100. regex = re.compile(r'.*win.zip')
  101. if regex.match(filename):
  102. self.win.append(base_url + artifact.find("relativePath").text)
  103. regex = re.compile(r'.*OSX.zip')
  104. if regex.match(filename):
  105. self.mac.append(base_url + artifact.find("relativePath").text)
  106. regex = re.compile(r'.*mac.zip')
  107. if regex.match(filename):
  108. self.mac.append(base_url + artifact.find("relativePath").text)
  109. regex = re.compile(r'.*b\d+.zip')
  110. if regex.match(filename):
  111. self.linux.append(base_url + artifact.find("relativePath").text)
  112. def download_server(self):
  113. if self.server == None:
  114. raise Exception("No server found")
  115. filename = os.path.basename(self.server)
  116. unzipped = filename.replace(".zip", "")
  117. if os.path.exists(unzipped):
  118. return unzipped
  119. if not os.path.exists(filename):
  120. print "Downloading %s..." % self.server
  121. urllib.urlretrieve(self.server, filename)
  122. if "false" == SKIPUNZIP.lower():
  123. if UNZIPARGS:
  124. command = [UNZIP, UNZIPARGS, filename]
  125. else:
  126. command = [UNZIP, filename]
  127. p = subprocess.Popen(command)
  128. rc = p.wait()
  129. if rc != 0:
  130. print "Couldn't unzip!"
  131. else:
  132. return unzipped
  133. print "Unzip and run again"
  134. sys.exit(0)
  135. class Email(object):
  136. def __init__(self, artifacts, server = SERVER,\
  137. sender = SENDER, recipients = RECIPIENTS,\
  138. weburl = WEBURL, subject = SUBJECT,\
  139. smtp_server = SMTP_SERVER):
  140. TO = ",".join(recipients)
  141. FROM = sender
  142. text = "The OMERO.server on %s has been upgraded. \n" \
  143. "=========================\n" \
  144. "THIS SERVER REQUIRES VPN!\n" \
  145. "=========================\n" \
  146. "Please download suitable clients from: \n " \
  147. "\n - Windows: \n %s\n " \
  148. "\n - MAC: \n %s\n " \
  149. "\n - Linux: \n %s\n " \
  150. "\n - Webclient available on %s. \n \n " %\
  151. (server, "\n".join(artifacts.win), "\n".join(artifacts.mac), "\
  152. \n".join(artifacts.linux), weburl)
  153. BODY = "\r\n".join((
  154. "From: %s" % FROM,
  155. "To: %s" % TO,
  156. "Subject: %s" % subject,
  157. "",
  158. text))
  159. server = smtplib.SMTP(smtp_server)
  160. server.sendmail(FROM, recipients, BODY)
  161. server.quit()
  162. print "Mail was sent to: %s" % ",".join(recipients)
  163. class Upgrade(object):
  164. def __init__(self, dir, cfg = CFG, mem = MEM, sym = SYM, skipweb = SKIPWEB):
  165. print "%s: Upgrading %s (%s)..." % (self.__class__.__name__, dir, sym)
  166. self.mem = mem
  167. self.sym = sym
  168. self.skipweb = skipweb
  169. _ = self.set_cli(self.sym)
  170. # Need lib/python set above
  171. import path
  172. self.cfg = path.path(cfg)
  173. self.dir = path.path(dir)
  174. self.stop(_)
  175. self.configure(_)
  176. self.directories(_)
  177. self.start(_)
  178. def stop(self, _):
  179. import omero
  180. try:
  181. print "Stopping server..."
  182. _("admin status --nodeonly")
  183. _("admin stop")
  184. except omero.cli.NonZeroReturnCode:
  185. pass
  186. if self.web():
  187. print "Stopping web..."
  188. self.stopweb(_)
  189. def configure(self, _):
  190. target = self.dir / "etc" / "grid" / "config.xml"
  191. if target.exists():
  192. print "Target %s already exists. Skipping..." % target
  193. return # Early exit!
  194. if not self.cfg.exists():
  195. print "%s not found. Copying old files" % self.cfg
  196. from path import path
  197. old_grid = path("OMERO-CURRENT") / "etc" / "grid"
  198. old_cfg = old_grid / "config.xml"
  199. old_cfg.copy(target)
  200. else:
  201. self.cfg.copy(target)
  202. _(["config", "set", "omero.web.server_list", WEB]) # TODO: Unneeded if copy old?
  203. for line in fileinput.input([self.dir / "etc" / "grid" / "templates.xml"], inplace=True):
  204. print line.replace("Xmx512M", self.mem).replace("Xmx256M", self.mem),
  205. def start(self, _):
  206. _("admin start")
  207. if self.web():
  208. print "Starting web ..."
  209. self.startweb(_)
  210. def set_cli(self, dir):
  211. dir = os.path.abspath(dir)
  212. lib = os.path.join(dir, "lib", "python")
  213. if not os.path.exists(lib):
  214. raise Exception("%s does not exist!" % lib)
  215. sys.path.insert(0, lib)
  216. import omero
  217. import omero.cli
  218. print "Using %s..." % omero.cli.__file__
  219. self.cli = omero.cli.CLI()
  220. self.cli.loadplugins()
  221. return self._
  222. def _(self, command):
  223. """
  224. Runs a command as if from the command-line
  225. without the need for using popen or subprocess
  226. """
  227. if isinstance(command, str):
  228. command = command.split()
  229. else:
  230. for idx, val in enumerate(command):
  231. command[idx] = val
  232. self.cli.invoke(command, strict=True)
  233. def web(self):
  234. return "false" == self.skipweb.lower()
  235. class UnixUpgrade(Upgrade):
  236. """
  237. def rmtree(self, d):
  238. def on_rmtree(self, func, name, exc):
  239. print "rmtree error: %s('%s') => %s" % (func.__name__, name, exc[1])
  240. d = path.path(d)
  241. d.rmtree(onerror = on_rmtree)
  242. """
  243. def stopweb(self, _):
  244. _("web stop")
  245. def startweb(self, _):
  246. _("web start")
  247. def confgure(self, _):
  248. super(UnixUpgrade, self).configure(_)
  249. var = self.dir / "var"
  250. var.mkdir()
  251. var.chmod(0755) # For Apache/Nginx
  252. def directories(self, _):
  253. try:
  254. os.unlink(self.sym)
  255. except:
  256. print "Failed to delete %s" % self.sym
  257. try:
  258. os.symlink(self.dir, self.sym)
  259. except:
  260. print "Failed to symlink %s to %s" % (self.dir, self.sym)
  261. class WindowsUpgrade(Upgrade):
  262. def stopweb(self, _):
  263. print "Removing web from IIS ..."
  264. _("web iis --remove")
  265. self.iisreset()
  266. def startweb(self, _):
  267. print "Configuring web in IIS ..."
  268. _("web iis")
  269. self.iisreset()
  270. def directories(self, _):
  271. self.rmdir()
  272. print "Should probably move directory to OLD_OMERO and test handles"
  273. self.mklink(self.dir)
  274. def call(self, command):
  275. rc = subprocess.call(command, shell=True)
  276. if rc != 0:
  277. print "*"*80
  278. print "Warning: '%s' returned with non-zero value: %s" % (command, rc)
  279. print "*"*80
  280. def rmdir(self):
  281. """
  282. """
  283. self.call("rmdir OMERO-CURRENT".split())
  284. def mklink(self, dir):
  285. """
  286. """
  287. self.call("mklink /d OMERO-CURRENT".split() + ["%s" % dir])
  288. def iisreset(self):
  289. """
  290. Calls iisreset
  291. """
  292. self.call(["iisreset"])
  293. if __name__ == "__main__":
  294. artifacts = Artifacts()
  295. if len(sys.argv) != 2:
  296. dir = artifacts.download_server()
  297. # Exits if directory does not exist!
  298. else:
  299. dir = sys.argv[1]
  300. if platform.system() != "Windows":
  301. u = UnixUpgrade(dir)
  302. else:
  303. u = WindowsUpgrade(dir)
  304. if "false" == SKIPEMAIL.lower():
  305. e = Email(artifacts)
  306. else:
  307. print "Skipping email..."