def api_perf_counters(): rc = get_rc() pc_data = {} for n in rc.network.list_network_status_v2(1): rc = RestClient(n['network_statuses'][0]['address'], 8000) rc.login('admin', app.config['API_PASSWORD']) resp = rc.request("GET", "/v1/metrics/") pc_data[n['node_id']] = resp return json.dumps(pc_data)
class qumulo_api: def __init__(self): self.rc = None self.creds = None def login(self, timeout=60): self.rc = RestClient(self.host, self.port, timeout=timeout) self.rc.login(self.user, self.password) def test_login(self, host, port, user, password): log_print("Logging into Qumulo Cluster [%s]" % host) try: self.host = host self.user = user self.password = password self.port = port self.login() log_print("Login succesful") except: log_print("Unable to connect to Qumulo Cluster %s via api" % host) log_print("Credentials used: username=%s, password=********" % user) print("Exception details: %s - %s" % (sys.exc_info()[0], sys.exc_info()[1])) print(traceback.format_exc()) log_print("Unable to connect to Qumulo Cluster %s via api" % host) log_print("Credentials used: username=%s, password=********" % user) sys.exit() def get_current_version(self): revision_id = self.rc.version.version()["revision_id"] self.version = revision_id.replace("Qumulo Core ", "") return self.version def get_platform(self): model_num = self.rc.cluster.list_node(1)["model_number"] model_num = model_num.lower() if "aws" in model_num: self.platform = "cloud" elif "cloud" in model_num: self.platform = "cloud" elif "gcp" in model_num: self.platform = "cloud" elif "hp" in model_num: self.platform = "hpe" else: self.platform = "qumulo" return self.platform def create_directory(self, full_path): m = re.match(r"^(.*?/)([^/]+)$", full_path) dir_path = m.groups()[0] name = m.groups()[1] if len(dir_path) > 1: dir_path = re.sub(r"/$", "", dir_path) if self.file_exists(full_path): log_print("Directory exists: %s" % full_path) else: try: self.rc.fs.create_directory(name=name, dir_path=dir_path) except: e = sys.exc_info()[1] if "fs_entry_exists_error" in str(e): log_print("Directory exists: %s" % full_path) else: log_print("Error creating directory '%s': %s" % (full_path, e)) def file_exists(self, full_path, size=None): try: print("Validating qimg file on cluster %s" % full_path) attr = self.rc.fs.get_file_attr(full_path) if size and int(attr["size"]) != size: log_print("File sizes different") log_print("Expected size: %s - size on Qumulo: %s" % (size, attr["size"])) return False except: return False return True def upgrade_arm(self, qimg_path): status = self.upgrade_status() if status != "UPGRADE_STATE_PREPARED": log_print("Can't arm in state: %s" % status) sys.exit() log_print("Begin upgrade arm process.") try: self.rc.request( "PUT", "/v1/upgrade/settings", body={ "install_path": qimg_path, "target": "UPGRADE_TARGET_ARM" }, ) except: exc = sys.exc_info()[1] time.sleep(20) msg = "Qumulo cluster armed with %s. Reloading Qumulo." log_print(msg % qimg_path) time.sleep(10) version_data = None while version_data == None: log_print("... Loading new Qumulo Software version: %s ..." % qimg_path) try: #### 10 second timeout for rest client while waiting. self.login(timeout=10) version_data = self.get_current_version() except: time.sleep(10) err_msg = "Completed upgrade to %s" log_print(err_msg % version_data) log_print("-" * 80) def upgrade_v2_arm(self, qimg_path): status = self.upgrade_v2_status() if status != "UPGRADE_STATE_PREPARED": log_print("Can't arm in state: %s" % status) sys.exit() log_print("Begin upgrade arm process.") try: resp = self.rc.upgrade_v2.commit() except: exc = sys.exc_info()[1] time.sleep(20) msg = "Qumulo cluster armed with %s. Reloading Qumulo." log_print(msg % qimg_path) time.sleep(10) version_data = None while version_data == None: log_print("... Loading new Qumulo Software version: %s ..." % qimg_path) try: #### 10 second timeout for rest client while waiting. self.login(timeout=10) version_data = self.get_current_version() except: time.sleep(10) err_msg = "Completed upgrade to %s" log_print(err_msg % version_data) log_print("-" * 80) def upgrade_prepare(self, version, qimg_path): log_print( "Preparing cluster for upgrade. Cluster will be fully available during this time." ) try: self.rc.request( "PUT", "/v1/upgrade/settings", body={ "install_path": qimg_path, "target": "UPGRADE_TARGET_PREPARE" }, ) except: exc = sys.exc_info()[1] log_print("!Fatal Error! Prepare exception: %s" % exc) sys.exit() status = self.upgrade_status() while status == "UPGRADE_STATE_PREPARING": log_print("Preparing...") time.sleep(17) status = self.upgrade_status() log_print("Upgrade prepared for: %s - status: %s" % (qimg_path, status)) def upgrade_v2_prepare(self, version, qimg_path): log_print( "Preparing cluster for upgrade. Cluster will be fully available during this time." ) try: self.rc.upgrade_v2.prepare(qimg_path, auto_commit=False) except: exc = sys.exc_info()[1] log_print("!Fatal Error! Prepare exception: %s" % exc) sys.exit() status = self.upgrade_v2_status() while status == "UPGRADE_STATE_PREPARING": log_print("Preparing...") time.sleep(17) status = self.upgrade_v2_status() log_print("Upgrade prepared for: %s - status: %s" % (qimg_path, status)) def upgrade_status(self): resp = self.rc.request("GET", "/v1/upgrade/status") state = resp["state"] error_state = resp["error_state"] log_print(f"{state} - {error_state}") if "error_message" in resp and resp["error_message"] != "": log_print("%s" % resp["error_message"].strip()) sys.exit() return resp["state"].replace("UPGRADE_", "UPGRADE_STATE_") def upgrade_v2_status(self): resp = self.rc.upgrade_v2.status() if resp.get("error_info", None) is not None: log_print("%s" % resp["error_info"].strip()) sys.exit() return resp["state"] def upgrade_to(self, version, qimg_path): if get_version_num(version) < get_version_num(UPGRADE_V2_CUTOVER): upgrade_status = self.upgrade_status upgrade_prepare = self.upgrade_prepare upgrade_arm = self.upgrade_arm else: upgrade_status = self.upgrade_v2_status upgrade_prepare = self.upgrade_v2_prepare upgrade_arm = self.upgrade_v2_arm status = upgrade_status( ) # formally stored in resp when this was a rc request if status == "UPGRADE_STATE_PREPARED": upgrade_arm(qimg_path) return # if resp["state"] != "UPGRADE_STATE_IDLE": # log_print("%(state)s - %(error_state)s" % resp) # if "error_message" in resp: # log_print("%s" % resp["error_message"].strip()) # if "is_blocked" in resp and resp["is_blocked"]: # log_print("Upgrade blocked: %(blocked_reason)s" % resp) # sys.exit() upgrade_prepare(version, qimg_path) upgrade_arm(qimg_path)
class QumuloConfigManager(): def __init__(self, hostname, user, password): self.hostname = hostname self.user = user self.password = password self.rc = RestClient(self.hostname, 8000) self.rc.login(self.user, self.password) self.date = date.today() def set_url(self, data_type, area=None, version=1, multiple=True): self.data_type = data_type self.multiple = multiple if area: self.data_full_name = "%s-%s" % (area, data_type) self.base_url = "/v%s/%s/%s%s" % (version, area, data_type, '/' if multiple else '') else: self.data_full_name = "%s" % (data_type, ) self.base_url = "/v%s/%s/" % (version, data_type) self.file_name = "qumulo-%s-%s-%s.json" % (self.date, self.hostname, self.data_full_name) def export_settings(self): print("\n--------------- export %10s settings ---------------" % self.data_type) more_data = True url = "%s%s" % (self.base_url, '?limit=1000' if self.multiple else '') objects = [] while url: d = self.rc.request("GET", url) if self.multiple == False or "roles" in url: objects = d url = None elif self.data_type == "quotas" or self.data_type == "policies": if 'entries' in d: for obj in d['entries']: objects.append(obj) else: for obj in d[self.data_type]: objects.append(obj) # handle pagination if 'paging' in d and d['paging']['next']: url = d['paging']['next'] else: url = None elif type(d) is list: for obj in d: objects.append(obj) url = None print("Saving %s %s objects to file %s" % (len(objects) if self.multiple else 1, self.data_full_name, self.file_name)) fw = open(self.file_name, "w") fw.write(json.dumps(objects, indent=2)) fw.close() def load_settings(self): print("\n--------------- load %10s settings ---------------" % self.data_type) if not os.path.exists(self.file_name): print("Settings file does not exist: %s" % self.file_name) return objects = json.loads(open(self.file_name, "r").read()) print("Found %s %s objects to load onto Qumulo cluster %s." % (len(objects), self.data_full_name, self.hostname)) object_success_count = 0 for obj in objects: try: if self.data_type == "policies": del obj['id'] for sched in obj['schedules']: del sched['id'] self.rc.request("POST", self.base_url, obj) object_success_count += 1 except Exception, e: print("failed to create %s - %s" % (self.data_type, e)) print("Created %s %s objects Qumulo cluster %s." % (object_success_count, self.data_full_name, self.hostname))