1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | import os
|
8 | import sys
|
9 | import re
|
10 | import shutil
|
11 | import tarfile
|
12 | from tempfile import mkstemp
|
13 | from optparse import OptionParser
|
14 |
|
15 | def get_hostname(config_file):
|
16 | hostname = ""
|
17 | global_settings_token_found = False
|
18 | hostname_token_line = 0
|
19 | with open(config_file, 'r') as f:
|
20 | for line in f:
|
21 | if global_settings_token_found:
|
22 | match = re.search('\s+hostname (.+)', line)
|
23 | if match:
|
24 | hostname = match.group(1)
|
25 | return hostname
|
26 | else:
|
27 | match = re.search('sys global-settings', line)
|
28 | if match:
|
29 | global_settings_token_found = True
|
30 |
|
31 | def get_ip(config_file):
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | ip = ""
|
43 | line_number = 0
|
44 | net_self_token_line = 0
|
45 | with open(config_file, 'r') as f:
|
46 | for line in f:
|
47 | match = re.search('net self', line)
|
48 | if match:
|
49 | net_self_token_line = line_number
|
50 |
|
51 | match = re.search(' address (.+)/(.+)', line)
|
52 | if match and (line_number - net_self_token_line == 1):
|
53 | ip = match.group(1)
|
54 | mask = match.group(2)
|
55 | line_number += 1
|
56 |
|
57 |
|
58 | return ip
|
59 |
|
60 |
|
61 | def get_local_ip():
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | ip = ""
|
69 | with open('/var/lib/dhclient/dhclient.leases', 'r') as f:
|
70 | for line in f:
|
71 | match = re.search('fixed-address (.+);', line)
|
72 | if match:
|
73 | ip = match.group(1)
|
74 |
|
75 | return ip
|
76 |
|
77 |
|
78 | def get_gateway(config_file):
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | gateway = ""
|
86 | with open(config_file, 'r') as f:
|
87 | for line in f:
|
88 | match = re.search(' gw (.+)', line)
|
89 | if match:
|
90 | gateway = match.group(1)
|
91 |
|
92 | return gateway
|
93 |
|
94 |
|
95 | def get_local_gateway():
|
96 |
|
97 |
|
98 |
|
99 | gateway = ""
|
100 | with open('/var/lib/dhclient/dhclient.leases', 'r') as f:
|
101 | for line in f:
|
102 | match = re.search('option routers (.+);', line)
|
103 | if match:
|
104 | gateway = match.group(1)
|
105 |
|
106 | return gateway
|
107 |
|
108 |
|
109 | def replace(source_file_path, pattern, substring):
|
110 | fh, target_file_path = mkstemp()
|
111 | with open(target_file_path, 'w') as target_file:
|
112 | with open(source_file_path, 'r') as source_file:
|
113 | for line in source_file:
|
114 | if "-" in pattern:
|
115 | newline = re.sub("(%s)$" %(pattern),substring,line)
|
116 | newline = re.sub("(%s)\." %(pattern),substring+'.',newline)
|
117 | target_file.write(newline)
|
118 | else:
|
119 | newline = re.sub("(%s)$" %(pattern),substring,line)
|
120 | newline = re.sub("(%s)\/" %(pattern),substring+'/',newline)
|
121 | target_file.write(newline)
|
122 | os.remove(source_file_path)
|
123 | shutil.move(target_file_path, source_file_path)
|
124 |
|
125 | def removeFiles(dir, pattern):
|
126 | if os.path.exists(dir):
|
127 | for f in os.listdir(dir):
|
128 | if re.search(pattern, f):
|
129 | os.remove(os.path.join(dir, f))
|
130 |
|
131 | def main():
|
132 |
|
133 | parser = OptionParser()
|
134 | parser.add_option("--debug-level", action="store", type="int", dest="debug_level", default=0, help="debug level print debug (0-9)")
|
135 | parser.add_option("--cloud-provider", action="store", type="string", dest="cloud_provider", default="" , help="Cloud being utilized, azure or aws, etc...")
|
136 | parser.add_option("--original-ucs", action="store", type="string", dest="original_ucs", help="Original UCS file name")
|
137 | parser.add_option("--updated-ucs", action="store", type="string", dest="updated_ucs", default="updated.ucs", help="Modified UCS file name")
|
138 | parser.add_option("--extract-directory", action="store", type="string", dest="extract_dir", default="ucs_extract_dir", help="name of directory to extract to")
|
139 | parser.add_option("--original-ucs-ip", action="store", type="string", dest="original_ucs_ip", help="ip in original ucs")
|
140 | parser.add_option("--original-ucs-gateway", action="store", type="string", dest="original_ucs_gateway", help="gateway in original ucs")
|
141 | parser.add_option("--dest-ip", action="store", type="string", dest="dest_ip", help="ip of destination instance")
|
142 | parser.add_option("--dest-gateway", action="store", type="string", dest="dest_gateway", help="gateway of destination instance")
|
143 | (options, args) = parser.parse_args()
|
144 |
|
145 |
|
146 | debug_level = options.debug_level
|
147 | cloud_provider = options.cloud_provider
|
148 | original_ucs = options.original_ucs
|
149 | updated_ucs = options.updated_ucs
|
150 | extract_ucs_dir = options.extract_dir
|
151 | original_ucs_ip = options.original_ucs_ip
|
152 | original_ucs_gateway = options.original_ucs_gateway
|
153 | dest_ip = options.dest_ip
|
154 | dest_gateway = options.dest_gateway
|
155 |
|
156 | if not original_ucs or not cloud_provider:
|
157 | print "Usage: "
|
158 | print (" ./%s --cloud-provider <aws | azure | gce> --original-ucs <ucs_filename>" % (sys.argv[0]))
|
159 | print (" ./%s --cloud-provider <aws | azure | gce> --original-ucs <ucs_filename> --updated-ucs <ucs_filename>" % (sys.argv[0]))
|
160 | print "ex. "
|
161 | print (" ./%s --cloud-provider aws --original-ucs original.ucs --updated-ucs updated.ucs" % (sys.argv[0]))
|
162 | sys.exit()
|
163 |
|
164 |
|
165 | tar_original = tarfile.open(original_ucs, "r:gz")
|
166 | tar_updated = tarfile.open(updated_ucs, "w:gz")
|
167 |
|
168 | try:
|
169 | tar_original.extractall(path=extract_ucs_dir)
|
170 | except IOError as e:
|
171 | sys.exit("I/O Error({0}): {1} - If the latest UCS file is corrupted and/or the current primary host is stuck at BECOMING_PRIMARY state, the corrupted UCS file needs to be deleted as well as primary host needs to be terminated to allow re-elect the new primary.'".format(e.errno, e.strerror))
|
172 |
|
173 |
|
174 | bigip_base_file = "/config/bigip_base.conf"
|
175 | if cloud_provider == 'aws':
|
176 | gateway_file = "/config/partitions/LOCAL_ONLY/bigip.conf"
|
177 | else:
|
178 | gateway_file = "/config/bigip.conf"
|
179 |
|
180 |
|
181 | dest_hostname = get_hostname(bigip_base_file)
|
182 | original_hostname = get_hostname(extract_ucs_dir + bigip_base_file)
|
183 |
|
184 |
|
185 | if not original_ucs_ip:
|
186 | original_ucs_ip = get_ip(extract_ucs_dir + bigip_base_file)
|
187 | if not original_ucs_gateway:
|
188 | original_ucs_gateway = get_gateway(extract_ucs_dir + gateway_file)
|
189 | if not dest_ip:
|
190 | if os.path.isfile(gateway_file):
|
191 | dest_ip = get_ip(bigip_base_file)
|
192 | else:
|
193 | dest_ip = get_local_ip()
|
194 | if not dest_gateway:
|
195 | if os.path.isfile(gateway_file):
|
196 | dest_gateway = get_gateway(gateway_file)
|
197 | else:
|
198 | dest_gateway = get_local_gateway()
|
199 |
|
200 | if debug_level > 0:
|
201 | print "original_hostname: " + original_hostname
|
202 | print "dest_hostname: " + dest_hostname
|
203 | print "original_ucs_ip: " + original_ucs_ip
|
204 | print "original_ucs_gateway: " + original_ucs_gateway
|
205 | print "dest_ip: " + dest_ip
|
206 | print "dest_gateway: " + dest_gateway
|
207 |
|
208 |
|
209 | original_ucs_ip_str = original_ucs_ip.replace(".", "-")
|
210 | dest_ip_str = dest_ip.replace(".", "-")
|
211 |
|
212 | if debug_level > 0:
|
213 | print "original_ucs_ip_str: " + original_ucs_ip_str
|
214 | print "dest_ip_str: " + dest_ip_str
|
215 |
|
216 | files_to_update = [
|
217 | "/config/bigip_base.conf",
|
218 | "/config/bigip.conf",
|
219 | "/config/BigDB.dat",
|
220 | "/SPEC-Manifest"
|
221 | ]
|
222 |
|
223 |
|
224 | replace(extract_ucs_dir + gateway_file, original_ucs_gateway, dest_gateway)
|
225 |
|
226 |
|
227 | for f in files_to_update:
|
228 | filename = extract_ucs_dir + f
|
229 | if debug_level > 0:
|
230 | print "updating : " + filename
|
231 | replace(filename, original_ucs_ip, dest_ip)
|
232 | replace(filename, original_ucs_ip_str, dest_ip_str)
|
233 | if original_hostname and dest_hostname:
|
234 | replace(filename, original_hostname, dest_hostname)
|
235 |
|
236 |
|
237 | path_to_exclude = "/config/cloud/" + cloud_provider
|
238 | shutil.rmtree(extract_ucs_dir + path_to_exclude, ignore_errors=True)
|
239 |
|
240 |
|
241 | shutil.rmtree(extract_ucs_dir + '/config/partitions/CloudLibsAutoscale', ignore_errors=True)
|
242 | shutil.rmtree(extract_ucs_dir + '/var/tmp/filestore_temp/files_d/CloudLibsAutoscale_d', ignore_errors=True)
|
243 | shutil.rmtree(extract_ucs_dir + '/config/partitions/CloudLibsLocal', ignore_errors=True)
|
244 | shutil.rmtree(extract_ucs_dir + '/var/tmp/filestore_temp/files_d/CloudLibsLocal_d', ignore_errors=True)
|
245 |
|
246 |
|
247 | removeFiles(extract_ucs_dir + '/config/cloud/keys', 'cloudLocal*')
|
248 |
|
249 |
|
250 | os.system("sed -i '/sys dynad key {/ { N ; /\\n[[:space:]]\+key[[:space:]]*\$M\$[^\\n]*/ { N; /\\n[[:space:]]*}/ { d } } }' " + extract_ucs_dir + "/config/bigip_base.conf")
|
251 |
|
252 | tar_updated.add(extract_ucs_dir, arcname='')
|
253 |
|
254 | tar_original.close()
|
255 | tar_updated.close()
|
256 |
|
257 | shutil.rmtree(extract_ucs_dir, ignore_errors=False, onerror=None)
|
258 |
|
259 | print "UCS Update Complete"
|
260 | print "Load UCS with command below:"
|
261 | print " tmsh load /sys ucs " + os.path.abspath(updated_ucs) + " no-license"
|
262 |
|
263 |
|
264 |
|
265 |
|
266 | if __name__ == "__main__":
|
267 | main()
|