-
Notifications
You must be signed in to change notification settings - Fork 2
/
add_attribute_insarmaps.py
executable file
·343 lines (272 loc) · 13.2 KB
/
add_attribute_insarmaps.py
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
#!/usr/bin/env python3
############################################################
# Program is part of MintPy #
# Copyright (c) 2013, Zhang Yunjun, Heresh Fattahi #
# Author: Alfredo Terrero, 2016 #
############################################################
import sys
import argparse
import psycopg2
import pycurl
from io import BytesIO
import urllib.request, urllib.parse, urllib.error
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from io import BytesIO
import mintpy.utils.readfile as readfile
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# TODO: fix these classes. apparantly, need to call commit() method after execute even if you fetch something
class InsarDatabaseController(object):
def __init__(self, username, password, host, db):
self.username = username
self.password = password
self.host = host
self.db = db
self.con = None
self.cursor = None
def connect(self):
try:
self.con = psycopg2.connect("dbname='pgis' user='" + self.username + \
"' host='" + self.host + "' password='" + self.password + "'")
self.cursor = self.con.cursor()
except Exception as e:
print("Error While Connecting")
print(e)
sys.exit()
def close(self):
self.con.close()
self.con = None
self.cursor = None
def run_raw_query(self, query):
self.cursor.execute(query)
self.con.commit()
if self.cursor.rowcount > 0:
return self.cursor.fetchall()
return None
def get_all_datasets(self):
sql = "SELECT * FROM area"
self.cursor.execute(sql)
return self.cursor.fetchall()
def list_dataset_names(self):
datasets = self.get_all_datasets()
for d in datasets:
print(d[0])
def get_dataset_id(self, dataset):
sql = "SELECT id from area WHERE area.unavco_name = '" + dataset + "'"
self.cursor.execute(sql)
id = self.cursor.fetchone()
if id:
return id[0]
return -1
def table_exists(self, table):
sql = "SELECT exists(SELECT * FROM information_schema.tables WHERE table_name=%s)"
self.cursor.execute(sql, (table,))
return self.cursor.fetchone()[0]
# TODO refactor below two functions
def attribute_exists_for_dataset(self, dataset, attributekey):
dataset_id = self.get_dataset_id(dataset)
sql = "SELECT exists(SELECT attributekey FROM extra_attributes WHERE area_id = " + \
str(dataset_id) + " AND attributekey = '" + attributekey + "');"
self.cursor.execute(sql)
return self.cursor.fetchone()[0]
def plot_attribute_exists_for_dataset(self, dataset, attributekey):
dataset_id = self.get_dataset_id(dataset)
sql = "SELECT exists(SELECT attributekey FROM plot_attributes WHERE area_id = " + \
str(dataset_id) + " AND attributekey = '" + attributekey + "');"
self.cursor.execute(sql)
return self.cursor.fetchone()[0]
def add_attribute(self, dataset, attributekey, attributevalue):
dataset_id = self.get_dataset_id(dataset)
sql = ""
prepared_values = None
sql = "CREATE TABLE IF NOT EXISTS extra_attributes (area_id integer, attributekey varchar, attributevalue varchar);"
self.cursor.execute(sql)
self.con.commit()
if not self.attribute_exists_for_dataset(dataset, attributekey):
sql = "INSERT INTO extra_attributes VALUES (%s, %s, %s);"
prepared_values = (str(dataset_id), attributekey, attributevalue)
else:
sql = "UPDATE extra_attributes SET attributevalue = %s WHERE area_id = %s AND attributekey = %s"
prepared_values = (attributevalue, str(dataset_id), attributekey)
self.cursor.execute(sql, prepared_values)
self.con.commit()
def add_plot_attribute(self, dataset, attributekey, plotAttributeJSON):
dataset_id = self.get_dataset_id(dataset)
sql = ""
prepared_values = None
sql = "CREATE TABLE IF NOT EXISTS plot_attributes (area_id integer, attributekey varchar, attributevalue json);"
self.cursor.execute(sql)
self.con.commit()
if not self.plot_attribute_exists_for_dataset(dataset, attributekey):
sql = "INSERT INTO plot_attributes VALUES (%s, %s, %s);"
prepared_values = (str(dataset_id), attributekey, plotAttributeJSON)
else:
sql = "UPDATE plot_attributes SET attributevalue = %s WHERE area_id = %s AND attributekey = %s"
prepared_values = (plotAttributeJSON, str(dataset_id), attributekey)
self.cursor.execute(sql, prepared_values)
self.con.commit()
def index_table_on(self, table, on, index_name):
# can't remove single quotes from table name, so we do it manually
sql = None
if index_name:
sql = 'CREATE INDEX "' + index_name + '" ON "' + table + '" (' + on + ');'
else:
sql = 'CREATE INDEX ON "' + table + '" (' + on + ');'
try:
self.cursor.execute(sql)
self.con.commit()
# index exists most probably if exception thrown
except Exception as e:
print(str(e))
def cluster_table_using(self, table, index_name):
sql = None
sql = 'CLUSTER "' + table + '" USING "' + index_name + '";'
try:
self.cursor.execute(sql)
self.con.commit()
# index exists most probably if exception thrown
except Exception as e:
print(str(e))
def remove_point_table_if_there(self, table_name):
sql = 'DROP TABLE IF EXISTS "' + table_name + '"'
self.cursor.execute(sql)
self.con.commit()
def create_area_table_if_not_exists(self):
# create area table if not exist - limit for number of dates is 2 00, limt for number of attribute keys/values is 100
msg = "CREATE TABLE IF NOT EXISTS area "
msg += "(unavco_name varchar, project_name varchar, "
msg += "longitude double precision, latitude double precision, "
msg += "country varchar, region varchar, numchunks integer, "
msg += "attributekeys varchar[100], attributevalues varchar[100], "
msg += "stringdates varchar[200], decimaldates double precision[200] );"
self.cursor.execute(msg)
self.con.commit()
def insert_dataset_into_area_table(self, area, project_name, mid_long, mid_lat,
country, region, chunk_num, attribute_keys,
attribute_values, string_dates_sql, decimal_dates_sql):
# put dataset into area table
query = "INSERT INTO area VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
preparedValues = (area, project_name, mid_long, mid_lat,
country, region, chunk_num, attribute_keys,
attribute_values, string_dates_sql, decimal_dates_sql)
self.cursor.execute(query, preparedValues)
self.con.commit()
def remove_dataset(self, unavco_name):
dataset_id = self.get_dataset_id(unavco_name)
if dataset_id == -1:
raise Exception("Dataset %s is not on insarmaps, so couldn't remove it"
% (unavco_name))
dataset_id_str = str(dataset_id)
self.remove_point_table_if_there(dataset_id_str)
# then try to delete from area and extra_attributes
try:
dataset_id = self.get_dataset_id(unavco_name)
sql = "DELETE from area WHERE id = " + dataset_id_str
self.cursor.execute(sql)
sql = "DELETE from extra_attributes WHERE area_id = " + dataset_id_str
self.cursor.execute(sql)
sql = "DELETE from plot_attributes WHERE area_id = " + dataset_id_str
self.cursor.execute(sql)
self.con.commit()
except Exception as e:
raise e
def get_disk_space(self):
# TODO: need to figure out why our certificate is not recognized anymore
return requests.get("https://" + self.host + "/diskSpace", verify=False).json()
class InsarDatasetController(InsarDatabaseController):
def __init__(self, username, password, host, db, serverUsername, serverPassword):
super(InsarDatasetController, self).__init__(username, password, host, db)
self.bodyOutput = BytesIO()
self.headersOutput = BytesIO()
self.serverUsername = serverUsername
self.serverPassword = serverPassword
def setup_curl(self):
curl = pycurl.Curl()
curl.setopt(curl.WRITEFUNCTION, self.bodyOutput.write)
curl.setopt(curl.HEADERFUNCTION, self.headersOutput.write)
curl.setopt(pycurl.COOKIEFILE, "")
curl.setopt(pycurl.SSL_VERIFYPEER, 0)
curl.setopt(pycurl.SSL_VERIFYHOST, 0)
# hackish way of finding if the host url gets redirected to https version of site
# TODO: find more elegant solution when time permits, and use requests instead of curl
# for all of these HTTP requests...
if self.host == "insarmaps.miami.edu":
self.host = requests.get("https://" + self.host, verify=False).url
return curl
def curl_login(self, username, password):
curl = self.setup_curl()
curl.setopt(curl.POST, 1)
loginParams = urllib.parse.urlencode([("email", username), ("password", password)])
curl.setopt(curl.POSTFIELDS, loginParams)
loginURL = self.host + "/auth/login"
curl.setopt(curl.URL, loginURL)
curl.perform()
return curl
def upload_mbtiles(self, fileName):
curl = self.curl_login(self.serverUsername, self.serverPassword)
curl.setopt(curl.HTTPPOST, [('title', fileName), (('file', (curl.FORM_FILE, fileName)))])
uploadURL = self.host + "/WebServices/uploadMbtiles"
curl.setopt(curl.URL, uploadURL)
buffer = BytesIO()
curl.setopt(curl.WRITEFUNCTION, buffer.write)
#curl.setopt(curl.VERBOSE, 1)
curl.perform()
responseCode = curl.getinfo(pycurl.HTTP_CODE)
if responseCode == 200:
print("Successfully uploaded " + fileName)
elif responseCode == 302:
sys.stderr.write("Server redirected us... Please check username and password, and try again\n")
elif responseCode == 301:
sys.stderr.write("Server redirected us... Please check host address, and try again\n")
else:
sys.stderr.write("The server responded with code: " + str(responseCode) + "\n")
print(buffer.getvalue().decode('UTF-8'))
def remove_mbtiles(self, fileName):
curl = self.curl_login(self.serverUsername, self.serverPassword)
curl.setopt(curl.HTTPPOST, [('fileName', fileName)])
deleteURL = self.host + "/WebServices/deleteMbtiles"
curl.setopt(curl.URL, deleteURL)
#curl.setopt(curl.VERBOSE, 1)
curl.perform()
responseCode = curl.getinfo(pycurl.HTTP_CODE)
if responseCode == 302:
sys.stderr.write("Server redirected us... Please check username and password, and try again")
elif responseCode == 301:
sys.stderr.write("Server redirected us... Please check host address, and try again")
def build_parser():
dbHost = "insarmaps.rsmas.miami.edu"
parser = argparse.ArgumentParser(description='Edit attributes of an insarmaps dataset')
required = parser.add_argument_group("required arguments")
required.add_argument("-f", "--folder", help="folder of the dataset to look for add_Attribute.txt", required=True)
required.add_argument("-u", "--user", help="username for the insarmaps database", required=True)
required.add_argument("-p", "--password", help="password for the insarmaps database", required=True)
required.add_argument("--host", default=dbHost, help="postgres DB URL for insarmaps database", required=True)
required.add_argument("-d", "--db", help="postgres database", required=True)
required.add_argument("-U", "--unavco_name", help="UNAVCO name of this dataset", required=True)
return parser
def main(argv):
parser = build_parser()
parseArgs = parser.parse_args()
username = parseArgs.user
password = parseArgs.password
host = parseArgs.host
db = parseArgs.db
working_dir = parseArgs.folder
# make sure we have a final / so the below code doesn't break
if working_dir[-1] != "/":
working_dir += "/"
unavco_name = parseArgs.unavco_name
attributes_file = working_dir + "add_Attribute.txt"
attributes = readfile.read_template(attributes_file)
dbController = InsarDatabaseController(username, password, host, db)
dbController.connect()
for key in attributes:
print("Setting attribute " + key + " to " + attributes[key])
if key == "plotAttributes":
dbController.add_plot_attribute(unavco_name, key, attributes[key])
else:
dbController.add_attribute(unavco_name, key, attributes[key])
dbController.index_table_on("extra_attributes", "area_id", "area_id_idx")
dbController.close()
if __name__ == '__main__':
main(sys.argv)