class Dorados(object): arrays = [] def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects self.filtering = len(objects) > 0 self.timeout = 10 if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): try: name = self.node.oget(s, 'name') except Exception: name = None if not name: name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "dorado": continue timeout = self.node.oget(s, "timeout") try: username = self.node.oget(s, "username") password = self.node.oget(s, "password") api = self.node.oget(s, "api") except: print("error parsing section", s, file=sys.stderr) continue try: secname, namespace, _ = split_path(password) password = factory("sec")(secname, namespace=namespace, volatile=True).decode_key("password") except Exception as exc: print("error decoding password: %s", exc, file=sys.stderr) continue self.arrays.append( Dorado(name, api, username, password, timeout, node=self.node)) done.append(name) def __iter__(self): for array in self.arrays: yield (array) def get_dorado(self, name): for array in self.arrays: if array.name == name: return array return None
class Centeras(object): def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects if len(objects) > 0: self.filtering = True else: self.filtering = False self.arrays = [] if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "centera": continue try: server = self.node.oget(s, "server") username = self.node.oget(s, "username") password = self.node.oget(s, "password") jcass_dir = self.node.oget(s, "jcass_dir") java_bin = self.node.oget(s, "java_bin") except: print("error parsing section", s, file=sys.stderr) try: secname, namespace, _ = split_path(password) password = factory("sec")(secname, namespace=namespace, volatile=True).decode_key("password") except Exception as exc: print("error decoding password: %s", exc, file=sys.stderr) continue self.arrays.append( Centera(name, server=server, username=username, password=password, java_bin=java_bin, jcass_dir=jcass_dir, node=self.node)) done.append(name) def __iter__(self): for array in self.arrays: yield (array)
class IbmDss(object): def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects self.filtering = len(objects) > 0 self.arrays = [] if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "ibmds": continue pwfile = os.path.join(Env.paths.pathvar, s + '.pwfile') if not os.path.exists(pwfile): raise ex.Error( "%s does not exists. create it with 'dscli managepwfile ...'" % pwfile) try: username = self.node.oget(s, "username") hmc1 = self.node.oget(s, "hmc1") hmc2 = self.node.oget(s, "hmc2") except Exception as exc: print("error parsing section %s: %s" % (s, exc), file=sys.stderr) continue self.arrays.append( IbmDs(name, hmc1, hmc2, username, pwfile, node=self.node)) done.append(name) def __iter__(self): for array in self.arrays: yield (array) def get(self, array): for o in self.arrays: if o.name == array: return o raise ex.Error( "%s not defined in the node/cluster configuration, or is not usable" % array)
class Netapps(object): def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects self.filtering = len(objects) > 0 self.arrays = [] if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "netapp": continue kwargs = {"node": self.node} for key in ("server", "username", "key"): try: kwargs[key] = self.node.oget(s, key) except: print("missing parameter: %s", s) if "server" not in kwargs or "username" not in kwargs or "key" not in kwargs: continue try: secname, namespace, _ = split_path(kwargs["password"]) kwargs["password"] = factory("sec")( secname, namespace=namespace, volatile=True).decode_key("password") except Exception as exc: print("error decoding password: %s", exc, file=sys.stderr) continue self.arrays.append(Netapp(s, **kwargs)) def __iter__(self): for array in self.arrays: yield (array)
class Brocades(object): switchs = [] def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects if len(objects) > 0: self.filtering = True else: self.filtering = False if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="switch"): name = self.node.oget(s, "name") if not name: name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "brocade": continue key = self.node.oget(s, "key") password = self.node.oget(s, "password") try: username = self.node.oget(s, "username") except: print("no 'username' parameter in section %s" % s) continue if key is None and password is None: print("no 'key' nor 'password' parameter in section %s" % s) continue self.switchs.append( Brocade(name, username, key, password, node=self.node)) done.append(name) def __iter__(self): for switch in self.switchs: yield (switch)
class IbmSvcs(object): def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects self.filtering = len(objects) > 0 self.arrays = [] if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "ibmsvc": continue try: username = self.node.oget(s, 'username') key = self.node.oget(s, 'key') except: print("error parsing section", s, file=sys.stderr) continue self.arrays.append(IbmSvc(name, username, key, node=self.node)) def __iter__(self): for array in self.arrays: yield(array)
class EmcVnxs(object): def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects if len(objects) > 0: self.filtering = True else: self.filtering = False self.arrays = [] if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "emcvnx": continue try: method = self.node.oget(s, "method") scope = self.node.oget(s, "scope") spa = self.node.oget(s, "spa") spb = self.node.oget(s, "spb") username = self.node.oget(s, "username") password = self.node.oget(s, "password") except Exception as exc: print("error parsing section %s: %s" % (s, exc), file=sys.stderr) continue if method == "credentials": if username is None or password is None: print( "error parsing section %s: username and password are mandatory" % s, file=sys.stderr) continue try: secname, namespace, _ = split_path(password) password = factory("sec")( secname, namespace=namespace, volatile=True).decode_key("password") except Exception as exc: print("error decoding password: %s", exc, file=sys.stderr) continue self.arrays.append( EmcVnx(name, method, scope, spa, spb, username=username, password=password, node=self.node)) done.append(name) def __iter__(self): for array in self.arrays: yield (array)
class Arrays(object): arrays = [] def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects self.filtering = len(objects) > 0 if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): try: name = self.node.oget(s, "name") except Exception: name = None if not name: name = s.split("#", 1)[-1] if name in done: continue if self.filtering and name not in self.objects: continue try: stype = self.node.oget(s, "type") except: continue if stype != "hds": continue try: bin = self.node.oget(s, 'bin') jre_path = self.node.oget(s, 'jre_path') url = self.node.oget(s, 'url') username = self.node.oget(s, 'username') password = self.node.oget(s, 'password') except Exception as exc: print("error parsing section %s: %s" % (s, exc), file=sys.stderr) continue try: secname, namespace, _ = split_path(password) password = factory("sec")(secname, namespace=namespace, volatile=True).decode_key("password") except Exception as exc: print("error decoding password: %s", exc, file=sys.stderr) continue self.arrays.append( Array(name, url, username, password, bin=bin, jre_path=jre_path, node=self.node)) done.append(name) def __iter__(self): for array in self.arrays: yield (array) def get_array(self, name): for array in self.arrays: if array.name == name: return array return None
class Evas(object): arrays = [] def __init__(self, objects=None, node=None): if objects is None: objects = [] self.objects = objects self.filtering = len(objects) > 0 if node: self.node = node else: self.node = Node() done = [] for s in self.node.conf_sections(cat="array"): name = s.split("#", 1)[-1] if name in done: continue try: stype = self.node.oget(s, "type") except: continue if stype != "eva": continue try: manager = self.node.oget(s, 'manager') username = self.node.oget(s, 'username') password = self.node.oget(s, 'password') sssubin = self.node.oget(s, 'bin') except Exception as exc: print("error parsing section %s: %s" % (s, exc), file=sys.stderr) pass try: secname, namespace, _ = split_path(password) password = factory("sec")(secname, namespace=namespace, volatile=True).decode_key("password") except Exception as exc: print("error decoding password: %s", exc, file=sys.stderr) continue out, err = sssu('ls system', manager, username, password, sssubin=sssubin) _in = False for line in out.split('\n'): if 'Systems avail' in line: _in = True continue if not _in: continue name = line.strip() if self.filtering and name not in self.objects: continue self.arrays.append( Eva(name, manager, username, password, sssubin=sssubin)) done.append(name) def __iter__(self): for array in self.arrays: yield (array)
class Nexenta(object): def __init__(self, head, log=None, node=None): self.object_type_cache = {} self.head = head self.auto_prefix = "svc:/system/filesystem/zfs/auto-sync:" self.username = None self.password = None self.port = 2000 if node: self.node = node else: self.node = Node() if log is not None: self.log = log else: self.log = self.node.log def init(self): if self.username is not None and self.password is not None: return s = "array#" + self.head try: stype = self.node.oget(s, "type") except Exception: raise ex.Error("no array configuration for head %s"%self.head) if stype != "nexenta": raise ex.Error("array %s type is not nexanta" % self.head) try: self.username = self.node.oget(s, "username") except Exception: raise ex.Error("no username information for head %s"%self.head) try: self.password = self.node.oget(s, "password") except Exception: raise ex.Error("no password information for head %s"%self.head) self.port = self.node.oget(s, "port") try: secname, namespace, _ = split_path(self.password) self.password = factory("sec")(secname, namespace=namespace, volatile=True).decode_key("password") except Exception as exc: raise ex.Error("error decoding password: %s" % exc) self.url = 'https://%(head)s:%(port)d/rest/nms/ <https://%(head)s:%(port)d/rest/nms/>'%dict(head=self.head, port=self.port) def rest(self, obj, method, params): self.init() data = {"method": method, "params": params, "object": obj} data = json.dumps(data) request = Request(self.url, data) base64string = base64.encodestring('%s:%s' % (self.username, self.password))[:-1] request.add_header('Authorization', 'Basic %s' % base64string) request.add_header('Content-Type' , 'application/json') try: response = urlopen(request) except URLError: raise ex.Error("unreachable head %s"%self.head) response = json.loads(response.read()) return response def dbus_auth_keys_list(self): data = self.rest("appliance", "dbus_auth_keys_list", []) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def ssh_list_bindings(self): data = self.rest("appliance", "ssh_list_bindings", []) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def ssh_unbind(self, user, hostport, force="0"): data = self.rest("appliance", "ssh_unbind", [user, hostport, force]) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def ssh_bind(self, user, hostport, password): data = self.rest("appliance", "ssh_bind", [user, hostport, password]) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def autosync_get_names(self): data = self.rest("autosync", "get_names", ['']) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def autosync_disable(self, name): if not name.startswith(self.auto_prefix): name = self.auto_prefix+name data = self.rest("autosync", "disable", [name]) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def autosync_enable(self, name): if not name.startswith(self.auto_prefix): name = self.auto_prefix+name data = self.rest("autosync", "enable", [name]) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def autosync_execute(self, name): if not name.startswith(self.auto_prefix): name = self.auto_prefix+name data = self.rest("autosync", "execute", [name]) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def autosync_get_state(self, name): if not name.startswith(self.auto_prefix): name = self.auto_prefix+name data = self.rest("autosync", "get_state", [name]) if data['error'] is not None: raise ex.Error(data['error']) return data['result'] def autosync_set_prop(self, name, prop, value): if not name.startswith(self.auto_prefix): name = self.auto_prefix+name data = self.rest("autosync", "set_child_prop", [name, prop, value]) if data['error'] is not None: raise ex.Error(data["error"]) return data['result'] def autosync_get_props(self, name): if not name.startswith(self.auto_prefix): name = self.auto_prefix+name data = self.rest("autosync", "get_child_props", [name, '']) if data['error'] is not None: raise ex.Error(data["error"]) return data['result'] def autosync_register(self, name): if not name.startswith(self.auto_prefix): name = self.auto_prefix+name data = self.rest("runner", "register", [name, {}, {}]) if data['error'] is not None: raise ex.Error(data["error"]) return data['result'] def zvol_clone(self, src, dst): data = self.rest("zvol", "clone", [src, dst]) if data['error'] is not None: raise ex.Error(data["error"]) def folder_clone(self, src, dst): data = self.rest("folder", "clone", [src, dst]) if data['error'] is not None: raise ex.Error(data["error"]) def clone(self, src, dst): snap = "@".join([src, dst.replace('/','_')]) object_type = self.object_type(src) if object_type == "folder": self.folder_clone(snap, dst) elif object_type == "zvol": self.zvol_clone(snap, dst) else: raise ex.Error("object type %s is not cloneable"%str(object_type)) def snapshot_create(self, src, dst, recursive=0): dst = dst.replace('/','_') object_type = self.object_type(src) if object_type == "folder": self.folder_snapshot(src, dst, recursive) elif object_type == "zvol": self.zvol_snapshot(src, dst, recursive) else: raise ex.Error("object type %s is not snapable"%str(object_type)) def zvol_snapshot(self, src, dst, recursive=0): data = self.rest("zvol", "create_snapshot", [src, dst, recursive]) if data['error'] is not None: raise ex.Error(data["error"]) def folder_snapshot(self, src, dst, recursive=0): snap = "@".join([src, dst]) data = self.rest("snapshot", "create", [snap, recursive]) if data['error'] is not None: raise ex.Error(data["error"]) def snapshot_destroy(self, src, dst, recursive=''): snap = "@".join([src, dst]) data = self.rest("snapshot", "destroy", [snap, recursive]) if data['error'] is not None: raise ex.Error(data["error"]) def snapshot_get_names(self): data = self.rest("snapshot", "get_names", ['']) if data['error'] is not None: raise ex.Error(data["error"]) return data['result'] def folder_get_names(self): data = self.rest("folder", "get_names", ['']) if data['error'] is not None: raise ex.Error(data["error"]) for folder in data['result']: self.object_type_cache[folder] = "folder" return data['result'] def zvol_get_names(self): data = self.rest("zvol", "get_names", ['']) if data['error'] is not None: raise ex.Error(data["error"]) for zvol in data['result']: self.object_type_cache[zvol] = "zvol" return data['result'] def object_type(self, o): if o in self.object_type_cache: return self.object_type_cache[o] if o in self.folder_get_names(): self.object_type_cache[o] = "folder" return "folder" elif o in self.zvol_get_names(): self.object_type_cache[o] = "zvol" return "zvol" else: raise ex.Error("can not determine type of object %s"%o) def set_prop(self, name, prop, val): otype = self.object_type(name) return self._set_prop(otype, name, prop, val) def _set_prop(self, otype, name, prop, val): data = self.rest(otype, "set_child_prop", [name, prop, val]) if data['error'] is not None: raise ex.Error(data["error"]) return data['result'] def get_props(self, name): otype = self.object_type(name) return self._get_props(otype, name) def _get_props(self, otype, name): data = self.rest(otype, "get_child_props", [name, '']) if data['error'] is not None: raise ex.Error(data["error"]) return data['result'] def set_can_mount(self, name): p = self.get_props(name) if not 'canmount' in p: return self.set_prop(name, "canmount", "on") def autosync_set_can_mount(self, name): folders = self.folder_get_names() props = self.autosync_get_props(name) if props['zfs/from-host'] == 'localhost': synchead = props['zfs/from-fs'] else: synchead = props['zfs/to-fs'] synchead = synchead.lstrip('/') for folder in folders: if not folder.startswith(synchead): continue self.set_can_mount(folder) self.log.info("set 'canmount = on' on folder %s"%folder) def snapclone(self, src, dst): self.snapshot_create(src, dst) self.clone(src, dst)