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

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

"""Logrotate module.""" 

import os 

import re 

 

from charmhelpers.core import hookenv 

 

LOGROTATE_DIR = "/etc/logrotate.d/" 

 

 

class LogrotateHelper: 

"""Helper class for logrotate charm.""" 

 

def __init__(self): 

"""Init function.""" 

self.retention = hookenv.config('logrotate-retention') 

self.override = hookenv.config('override') 

self.override_files = self.get_override_files() 

self.override_settings = self.get_override_settings() 

 

def read_config(self): 

"""Read changes from disk. 

 

Config changed/install hooks dumps config out to disk, 

Here we read that config to update the cronjob 

""" 

config_file = open("/etc/logrotate_cronjob_config", "r") 

lines = config_file.read() 

lines = lines.split('\n') 

 

self.retention = int(lines[2]) 

 

def modify_configs(self): 

"""Modify the logrotate config files.""" 

for config_file in os.listdir(LOGROTATE_DIR): 

file_path = LOGROTATE_DIR + config_file 

 

logrotate_file = open(file_path, 'r') 

content = logrotate_file.read() 

logrotate_file.close() 

 

mod_contents = self.modify_content(content, file_path) 

 

mod_contents = self.modify_header(mod_contents) 

 

logrotate_file = open(file_path, 'w') 

logrotate_file.write(mod_contents) 

logrotate_file.close() 

 

def get_override_files(self): 

"""Return paths for files to be overrided.""" 

return [path['path'] for path in self.override 

if self.override.keys() == ['path', 'rotate', 'interval']] 

 

def get_override_settings(self, file_path): 

"""Return paths for files to be overrided.""" 

for override_entry in self.override: 

if file_path == override_entry['path']: 

rotate = override_entry['rotate'] 

interval = override_entry['interval'] 

return {'rotate': rotate, 'interval': interval} 

 

def modify_content(self, content, file_path): 

"""Edit the content of a logrotate file.""" 

# Split the contents in a logrotate file in separate entries (if 

# multiple are found in the file) and put in a list for further 

# processing 

split = content.split('\n') 

items = [] 

string = "" 

for row in split: 

string += row + '\n' 

if '}' in row: 

items.append(string) 

string = "" 

continue 

 

# Work on each item - checking the rotation configuration and setting 

# the rotate option to the appropriate value 

results = [] 

for item in items: 

# Override rotate, if defined 

if file_path in self.override_files: 

count = self.override_settings['rotate'] 

else: 

count = self.calculate_count(item, self.retention) 

rotate = 'rotate {}'.format(count) 

# if rotate is missing, add it as last line in the item entry 

if 'rotate' in item: 

result = re.sub(r'rotate \d+\.?[0-9]*', rotate, item) 

else: 

result = item.replace('}', ' ' + rotate + '\n}') 

results.append(result) 

 

results = '\n'.join(results) 

 

# Override interval, if defined 

if file_path in self.override_files: 

interval = self.override_settings['interval'] 

regex = re.compile("(daily|weekly|monthly|yearly)") 

results = regex.sub(interval, results) 

 

return results 

 

def modify_header(self, content): 

"""Add Juju headers to the file.""" 

header = "# Configuration file maintained by Juju. Local changes may be overwritten" 

 

split = content.split('\n') 

if split[0].startswith(header): 

result = content 

else: 

result = header + '\n' + content 

 

return result 

 

@classmethod 

def calculate_count(cls, item, retention): 

"""Calculate rotate based on rotation interval. Always round up.""" 

# Fallback to default lowest retention - days 

# better to keep the logs than lose them 

count = retention 

# Daily 1:1 to configuration retention period (in days) 

if 'daily' in item: 

count = retention 

# Weekly rounding up, as weeks are 7 days 

if 'weekly' in item: 

count = int(round(retention/7)) 

# Monthly default 30 days and round up because of 28/31 days months 

if 'monthly' in item: 

count = int(round(retention/30)) 

# For every 360 days - add 1 year 

if 'yearly' in item: 

count = retention // 360 + 1 if retention > 360 else 1 

 

return count