Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Stefan Countryman, September 14, 2016 

2 

3""" 

4FileHandlers that upload files to gw-astronomy.org/gwhen and record successful 

5uploads with logfile receipts. 

6""" 

7 

8import logging 

9from subprocess import Popen, PIPE 

10from llama.filehandler import GenerationError 

11from llama.com.utils import UploadReceipt 

12from llama.files.skymap_info import SkymapInfo 

13from llama.files.lvc_gcn_xml import LvcGcnXml, LvcRetractionXml 

14from llama.files.lvalert_json import LVAlertJSON 

15 

16LOGGER = logging.getLogger(__name__) 

17 

18 

19# The following class is abstract, so we shouldn't need to define abstract 

20# methods. 

21# pylint: disable=abstract-method 

22class GWAstroReceipt(UploadReceipt): 

23 """ 

24 A log file created indicating successful upload of some other original 

25 file to gw-astronomy.org. 

26 """ 

27 

28 FILENAME_FMT = "rct_gwa_{}.log" 

29 REMOTE_RUNDIR = '/home/gwhen/content/events/' 

30 REMOTE_URL = 'gw-astronomy.org' 

31 REMOTE_USER = 'gwhen' 

32 CLASSNAME_FMT = 'RctGwa{}' 

33 

34 @classmethod 

35 def set_class_attributes(cls, subclass): 

36 """ 

37 See ``UploadReceipt.set_class_attributes``; this method adds 

38 ``SkymapInfo`` to ``subclass.DEPENDENCIES`` if it is not already a 

39 member and ``RSYNC_DEST``, the destination directory for uploaded 

40 events. 

41 """ 

42 super().set_class_attributes(subclass) 

43 if SkymapInfo not in subclass.DEPENDENCIES: 

44 subclass.DEPENDENCIES = tuple(subclass.DEPENDENCIES)+(SkymapInfo,) 

45 subclass.RSYNC_DEST = (f"{subclass.REMOTE_USER}@{subclass.REMOTE_URL}:" 

46 f"{subclass.REMOTE_RUNDIR}") 

47 return subclass 

48 

49 @property 

50 def rsync_source(self): 

51 """Get the source path for an ``rsync`` upload to a remote server 

52 (including the proper ``--relative`` dot in the path to ensure 

53 subdirectory creation serverside).""" 

54 return f"{self.rundir}/./{self.eventid}/{self.FILENAME}" 

55 

56 def _generate(self): # pylint: disable=arguments-differ 

57 cmd = ['rsync', '-rtRv', '--chmod=+r', self.rsync_source, 

58 self.RSYNC_DEST] 

59 proc = Popen(cmd, stdout=PIPE, stderr=PIPE) 

60 res, err = proc.communicate() 

61 msg = (f"CMD: {' '.join(cmd)}\nSTDOUT:\n" 

62 f"{res.decode()}\nSTDERR:\n{err.decode()}\n") 

63 if proc.returncode: 

64 LOGGER.error(f"FAILED.\n{msg}") 

65 raise GenerationError(msg) 

66 with open(self.fullpath, 'w') as outfile: 

67 outfile.write(f"SUCCESS.\n{msg}") 

68 

69 

70# must register these here to avoid circular imports since SkymapInfo imports 

71# them all first 

72GWAstroReceipt.upload_this()(SkymapInfo) 

73GWAstroReceipt.upload_this()(LvcGcnXml) 

74GWAstroReceipt.upload_this()(LvcRetractionXml) 

75GWAstroReceipt.upload_this()(LVAlertJSON)