@@ -8,108 +8,177 @@ import getopt
8
8
import os
9
9
10
10
import yaml
11
+
11
12
from foreman .foreman import *
12
13
13
14
15
+ def ensure_dir (dir ):
16
+ if not os .path .exists (dir ):
17
+ os .makedirs (dir )
18
+
19
+
20
+ def remove_keys_from_dict (keys , data ):
21
+ for key in keys :
22
+ if key in data :
23
+ data .pop (key )
24
+ return data
25
+
26
+
27
+ def clear_data (data , invalid_keys ):
28
+ if isinstance (data , list ):
29
+ for i in range (len (data )):
30
+ data [i ] = clear_data (data = data [i ], invalid_keys = invalid_keys )
31
+ elif isinstance (data , dict ):
32
+ data = remove_keys_from_dict (keys = invalid_keys , data = data )
33
+ for key in data :
34
+ data [key ] = clear_data (data [key ], invalid_keys = invalid_keys )
35
+ return data
36
+
37
+
14
38
class ForemanBackup :
15
- def __init__ (self , hostname , port , username , password , katello_support = False , backup_dir = '.' ):
16
- self .foreman = Foreman (hostname , port , username , password )
17
- self .backup_dir = backup_dir
18
- self .katello_support = katello_support
39
+ def __init__ (self , ** kwargs ):
40
+ self .foreman = Foreman (kwargs .get ('hostname' ),
41
+ kwargs .get ('port' ),
42
+ kwargs .get ('username' ),
43
+ kwargs .get ('password' ))
44
+ self .backup_dir = kwargs .get ('backup_dir' , '.' )
45
+ self .katello_support = kwargs .get ('katello_support' , False )
46
+
47
+ def get_resources (self , type , resource_function ):
48
+ result = list ()
49
+ try :
50
+ resources = resource_function ()
51
+ for i in range (len (resources )):
52
+ item = resources [i ]
53
+ if 'id' in item :
54
+ try :
55
+ resource = self .get_resource (type = type , id = resources [i ].get ('id' ))
56
+ except ForemanError as e :
57
+ # There seems to be a bug in Foreman 1.7.3 whereas the API reports 404
58
+ # while executing a get request on organizations/:id
59
+ # API: http://theforeman.org/api/apidoc/v2/organizations/show.html
60
+ if e .status_code == 404 :
61
+ resource = item
62
+ else :
63
+ resource = item
64
+ result .append (resource )
65
+ return result
66
+ except ForemanError as e :
67
+ print ('Error on getting resource {0}' .format (e .message ))
68
+ exit (1 )
19
69
20
- def backup (self , resource , resource_function ):
21
- """Backup Foreman resource as YAML file into a directory.
70
+ def get_resource (self , type , id ):
71
+ return self . foreman . get_resource ( resource_type = type , resource_id = id )
22
72
23
- A new directory named <resource> will be created inside <backup_dir>. Each
73
+ def write_resources (self , type , items , backup_dir ):
74
+ """Backup Foreman type as YAML file into a directory.
75
+
76
+ A new directory named <type> will be created inside <backup_dir>. Each
24
77
resource fetched by <resource_function> will be saved in an own YAML file
25
- called <resource_name>.yaml in <backup_dir>/<resource >.
78
+ called <resource_name>.yaml in <backup_dir>/<type >.
26
79
27
80
Args:
28
81
backup_dir (str): Directory where to create the backup files
29
- resource (str): Name of the resource to backup (e.g. 'architectures')
82
+ type (str): Name of the resource to backup (e.g. 'architectures')
30
83
resource_function (def): Name of function to call to get a dict of resources
31
84
"""
32
- backup_dir = os .path .join (self .backup_dir , resource )
33
-
34
- resources = resource_function ()
35
- print ('Backing up {0} {1}' .format (str (len (resources )), resource ))
36
-
37
- if not os .path .exists (backup_dir ):
38
- os .makedirs (backup_dir )
39
-
40
- for resource_item in resources :
41
- item = None
42
- if 'id' in resource_item :
43
- resource_id = resource_item .get ('id' )
44
- try :
45
- item = self .foreman .get_resource (resource_type = resource , resource_id = resource_id )
46
- except ForemanError as e :
47
- # There seems to be a bug in Foreman 1.7.3 whereas the API reports 404
48
- # while executing a get request on organizations/:id
49
- # API: http://theforeman.org/api/apidoc/v2/organizations/show.html
50
- if e .status_code == 404 :
51
- item = resource_item
52
-
53
- if item :
54
- if 'title' in item :
55
- file_name = item .get ('title' )
56
- elif 'login' in item :
57
- file_name = item .get ('login' )
58
- elif 'name' in item :
59
- file_name = item .get ('name' )
60
- else :
61
- print ('Can\' t backup {0}' .format (item ))
62
- continue
63
- backup_file = os .path .join (backup_dir , file_name .replace ('/' , '_' ) + '.yaml' )
64
- with open (backup_file , 'w' ) as backup_file :
65
- yaml .safe_dump (item , backup_file , default_flow_style = False )
85
+ backup_dir = os .path .join (self .backup_dir , type )
86
+ ensure_dir (dir = backup_dir )
87
+
88
+ for resource in items :
89
+ if 'title' in resource :
90
+ file_name = resource .get ('title' )
91
+ elif 'login' in resource :
92
+ file_name = resource .get ('login' )
93
+ elif 'name' in resource :
94
+ file_name = resource .get ('name' )
95
+ else :
96
+ print ('Can\' t backup {0}' .format (resource ))
97
+ continue
98
+ backup_file_name = os .path .join (backup_dir , '{name}' .format (name = file_name .replace ('/' , '_' ) + '.yaml' ))
99
+ with open (backup_file_name , 'w' ) as backup_file :
100
+ yaml .safe_dump (resource , backup_file , default_flow_style = False )
101
+
102
+
103
+ def backup (self , resource_type , resource_function ):
104
+ resources = self .get_resources (type = resource_type , resource_function = resource_function )
105
+ print ('Backing up {count} {resource_type}' .format (count = str (len (resources )), resource_type = resource_type ))
106
+ self .write_resources (type = resource_type , items = resources , backup_dir = self .backup_dir )
66
107
67
108
def run (self ):
68
- self .backup_foreman ()
109
+ ensure_dir (self .backup_dir )
110
+ self .backup_resources ()
69
111
if self .katello_support :
70
112
self .backup_katello ()
71
113
72
- def backup_foreman (self ):
114
+ def backup_resources (self ):
73
115
74
- self .backup (resource = 'architectures' ,
116
+ self .backup (resource_type = 'architectures' ,
75
117
resource_function = self .foreman .get_architectures )
76
- self .backup (resource = 'common_parameters' ,
118
+ self .backup (resource_type = 'common_parameters' ,
77
119
resource_function = self .foreman .get_common_parameters )
78
- self .backup (resource = 'compute_resources' ,
120
+ self .backup (resource_type = 'compute_resources' ,
79
121
resource_function = self .foreman .get_compute_resources )
80
- self .backup (resource = 'compute_profiles' ,
122
+ self .backup (resource_type = 'compute_profiles' ,
81
123
resource_function = self .foreman .get_compute_profiles )
82
- self .backup (resource = 'config_templates' ,
124
+ self .backup (resource_type = 'config_templates' ,
83
125
resource_function = self .foreman .get_config_templates )
84
- self .backup (resource = 'domains' ,
126
+ self .backup (resource_type = 'domains' ,
85
127
resource_function = self .foreman .get_domains )
86
- self .backup (resource = 'environments' ,
128
+ self .backup (resource_type = 'environments' ,
87
129
resource_function = self .foreman .get_environments )
88
- self .backup (resource = 'hosts' ,
130
+ self .backup (resource_type = 'hosts' ,
89
131
resource_function = self .foreman .get_hosts )
90
- self .backup (resource = 'hostgroups' ,
132
+ self .backup (resource_type = 'hostgroups' ,
91
133
resource_function = self .foreman .get_hostgroups )
92
- self .backup (resource = 'media' ,
134
+ self .backup (resource_type = 'media' ,
93
135
resource_function = self .foreman .get_media )
94
- self .backup (resource = 'operatingsystems' ,
136
+ self .backup (resource_type = 'operatingsystems' ,
95
137
resource_function = self .foreman .get_operatingsystems )
96
- self .backup (resource = 'roles' ,
138
+ self .backup (resource_type = 'roles' ,
97
139
resource_function = self .foreman .get_roles )
98
- self .backup (resource = 'smart_proxies' ,
140
+ self .backup (resource_type = 'smart_proxies' ,
99
141
resource_function = self .foreman .get_smart_proxies )
100
- self .backup (resource = 'subnets' ,
142
+ self .backup (resource_type = 'subnets' ,
101
143
resource_function = self .foreman .get_subnets )
102
- self .backup (resource = 'users' ,
144
+ self .backup (resource_type = 'users' ,
103
145
resource_function = self .foreman .get_users )
104
146
105
147
106
148
def backup_katello (self ):
107
- self .backup (resource = 'locations' ,
149
+ self .backup (resource_type = 'locations' ,
108
150
resource_function = self .foreman .get_locations )
109
- self .backup (resource = 'organizations' ,
151
+ self .backup (resource_type = 'organizations' ,
110
152
resource_function = self .foreman .get_organizations )
111
153
112
154
155
+ class AnsibleBackup (ForemanBackup ):
156
+ invalid_keys = ['created_at' , 'updated_at' , 'id' ]
157
+
158
+ def __init__ (self , ** kwargs ):
159
+ ForemanBackup .__init__ (self , ** kwargs )
160
+
161
+
162
+ def write_resources (self , type , items , backup_dir ):
163
+ backup_file_name = os .path .join (backup_dir , type )
164
+ resources = list ()
165
+ for i in range (len (items )):
166
+ item = self .get_resource (type = type , id = items [i ].get ('id' ))
167
+ item = clear_data (item , invalid_keys = self .invalid_keys )
168
+ item ['state' ] = 'present'
169
+ resources .append (item )
170
+
171
+ with open (backup_file_name , 'w' ) as f :
172
+ f .write ('---\n ' )
173
+ f .write ('foreman_{resource}:' .format (resource = type ))
174
+ if len (resources ) > 0 :
175
+ f .write ('\n ' )
176
+ else :
177
+ f .write (' ' )
178
+ with open (backup_file_name , 'a' ) as f :
179
+ yaml .safe_dump (resources , f , default_flow_style = False )
180
+
181
+
113
182
def show_help ():
114
183
"""Print on screen how to use this script.
115
184
"""
@@ -133,11 +202,13 @@ def main(argv):
133
202
foreman_port = os .environ .get ('FOREMAN_PORT' , '443' )
134
203
foreman_user = os .environ .get ('FOREMAN_USER' , 'foreman' )
135
204
foreman_pass = os .environ .get ('FOREMAN_PASS' , 'changme' )
136
- katello_support = string2bool (os .environ .get ('FOREMAN_KATELLO_SUPPORT' , 'False' ))
205
+ ansible_format = os .environ .get ('FOREMAN_BACKUP_ANSIBLE_FORMAT' , False )
206
+ backup_dir = os .environ .get ('FOREMAN_BACKUP_DIR' , '.' )
207
+ katello_support = string2bool (os .environ .get ('FOREMAN_KATELLO_SUPPORT' , False ))
137
208
138
209
try :
139
210
opts , args = getopt .getopt (argv ,
140
- "f:hu:p:s:k" ,
211
+ "ab: f:hu:p:s:k" ,
141
212
["foreman=" , "username=" , "port=" , "secret=" ])
142
213
except getopt .GetoptError :
143
214
show_help ()
@@ -150,16 +221,28 @@ def main(argv):
150
221
sys .exit ()
151
222
elif opt == '-k' :
152
223
katello_support = True
224
+ elif opt == '-a' :
225
+ ansible_format = True
226
+ elif opt == '-b' :
227
+ backup_dir = arg
153
228
elif opt in ('-u' , '--username' ):
154
229
foreman_username = arg
155
230
elif opt in ('-p' , '--port' ):
156
231
foreman_port = arg
157
232
elif opt in ('-s' , '--secret' ):
158
233
foreman_password = arg
159
234
160
- backup = ForemanBackup (foreman_host , foreman_port ,
161
- foreman_user , foreman_pass ,
162
- katello_support )
235
+ if ansible_format :
236
+ backup_class = AnsibleBackup
237
+ else :
238
+ backup_class = ForemanBackup
239
+
240
+ backup = backup_class (hostname = foreman_host ,
241
+ port = foreman_port ,
242
+ username = foreman_user ,
243
+ password = foreman_pass ,
244
+ katello_support = katello_support ,
245
+ backup_dir = backup_dir )
163
246
backup .run ()
164
247
165
248
0 commit comments