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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

#/usr/bin/env python 

 

""" 

@file ion/services/dm/inventory/ncml_generator.py 

@author Paul Hubbard 

@author Matt Rodriguez 

@date 4/29/11 

@brief For each dataset in the inventory, create a corresponding NcML file and 

sync with remove server. Some tricky code for running a process and noting its 

exit with a deferred. 

""" 

 

# File template. The filename and 'location' are just the GUID. 

# Note the %s for string substitution. 

file_template = """<?xml version="1.0" encoding="UTF-8"?>\n<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2" location="ion://%s"/> 

""" 

 

from os import path, environ, listdir, remove 

import fnmatch 

import os 

 

from twisted.internet import defer 

from ion.util.os_process import OSProcess 

 

import ion.util.ionlog 

from ion.core import ioninit 

 

# Globals and config file variables 

log = ion.util.ionlog.getLogger(__name__) 

CONF = ioninit.config(__name__) 

RSYNC_CMD = CONF['rsync'] 

 

def create_ncml(id_ref, filepath=""): 

    """ 

    @brief for a given idref, generate an NcML file in the filepath directory 

    @param filepath Output directory, defaults to current working directory 

    @param id_ref idref object from which we pull GUID 

    @retval File contents, as a string, or None if error 

    """ 

 

    full_filename = path.join(filepath, id_ref + '.ncml') 

    log.debug('Generating NcML file %s' % full_filename) 

    try: 

        fh = open(full_filename, 'w') 

        fh.write(file_template % id_ref) 

        fh.close() 

    except IOError: 

        log.exception('Error writing NcML file') 

        return None 

 

    return file_template % id_ref 

 

def check_for_ncml_files(local_filepath): 

    """ 

    Check for ncml files on disk. 

     

    Returns True if any ncml files in the given directory, False if no files 

        or an error is raised. 

    """ 

    log.debug('checking for ncml files in %s' % local_filepath) 

 

    try: 

        allfiles = listdir(local_filepath) 

        log.debug("all files %s" % (allfiles,)) 

        ncml_files = [] 

        for fname in allfiles: 

            log.debug("Got file %s" % (fname,)) 

            if fnmatch.fnmatch(fname, '*.ncml'): 

                ncml_files.append(fname) 

    except IOError: 

        log.exception('Error searching %s for ncml files' % local_filepath) 

        return False 

 

    log.debug("len(ncml_files): %s"% (len(ncml_files),)) 

    if len(ncml_files) > 0: 

        return True 

 

    return False 

 

 

def clear_ncml_files(local_filepath): 

    """ 

    Clear ncml files on disk. 

    """ 

    log.debug('clearing ncml files in %s' % local_filepath) 

 

    try: 

        allfiles = listdir(local_filepath) 

        ncml_files = [] 

        for file in allfiles: 

            if fnmatch.fnmatch(file, '*.ncml'): 

                fpath = path.join(local_filepath, file) 

                log.debug('Removing file: %s' % fpath) 

                remove(fpath) 

    except IOError: 

        log.exception('Error searching %s for ncml files' % local_filepath) 

        return False 

 

    if len(ncml_files) > 0: 

        return True 

 

    return False 

 

 

 

def rsync_ncml(local_filepath, server_url): 

    """ 

    @brief Method to perform a bidirectional sync with a remote server, 

    probably via rsync, unison or similar. Should be called after generating all 

    local ncml files. 

    @param local_filepath Local directory for writing ncml file(s) 

    @param server_url rsync URL of the server 

    @retval Deferred that will callback when rsync exits, or errback if rsync fails 

    """ 

 

    # Use /bin/bash to execute this: 

 

    # Set up the rsync command: 

    arg1 = " ".join([ 'rsync', '-r', '--perms', '--include=*.ncml', '--exclude=*', 

            '-v', '-h', '--delete-excluded', local_filepath , server_url]) 

 

    # Execute via /bin/bash -c to get terminal like behavior 

    args = ['-c', arg1 ] 

 

 

    log.debug("rsync command %s " % (RSYNC_CMD,)) 

 

    env_data = environ.copy() 

 

    ssh_cmd = "".join(("ssh -o StrictHostKeyChecking=no ")) 

    env_data["RSYNC_RSH"] =  ssh_cmd 

 

    rp = OSProcess(binary=RSYNC_CMD, spawnargs=args, env=env_data) 

    log.debug('Command is "%s"'% ' '.join(args)) 

    return rp.spawn() 

 

 

 

@defer.inlineCallbacks 

def do_complete_rsync(local_ncml_path, server_url): 

    """ 

    Orchestration routine to tie it all together plus cleanup at the end. 

    Needs the inlineCallbacks to serialise. 

 

    @TODO remove this now useless method... 

    """ 

 

    yield rsync_ncml(local_ncml_path, server_url)