Example #1
0
def build_services(status=None, paths=None, create_instance=False, node=None):
    """
    Returns a list of all services of status matching the specified status.
    If no status is specified, returns all services.
    """
    if paths is None:
        paths = []

    errors = []
    services = {}

    if isinstance(paths, str):
        paths = [paths]

    if len(paths) == 0:
        paths = list_services()
        missing_paths = []
    else:
        local_paths = list_services()
        missing_paths = sorted(list(set(paths) - set(local_paths)))
        for m in missing_paths:
            name, namespace, kind = split_path(m)
            if create_instance:
                services[m] = factory(kind)(name, namespace, node=node)
            else:
                # foreign service
                services[m] = factory(kind)(name,
                                            namespace,
                                            node=node,
                                            volatile=True)
        paths = list(set(paths) & set(local_paths))

    for path in paths:
        name, namespace, kind = split_path(path)
        try:
            svc = factory(kind)(name, namespace, node=node)
        except (ex.Error, ex.InitError, ValueError,
                utilities.configparser.Error) as e:
            errors.append("%s: %s" % (path, str(e)))
            node.log.error(str(e))
            continue
        except ex.AbortAction:
            continue
        except:
            import traceback
            traceback.print_exc()
            continue
        services[svc.path] = svc
    return [s for _, s in sorted(services.items())], errors
Example #2
0
 def on_create(self):
     changes = []
     has_ca = False
     if not self.oget("DEFAULT", "cn"):
         if self.namespace == "system":
             changes.append("cn=%s" % self.name)
         else:
             changes.append("cn=%s" % self.fullname)
     if self.namespace != "system":
         try:
             self.conf_get("DEFAULT", "validity")
         except ex.OptNotFound:
             changes.append("validity=%s" % DEFAULT_SACC_CERT_VALIDITY)
         grant = "guest:" + self.namespace
         changes.append("grant=%s" % grant)
     if not self.oget("DEFAULT", "ca"):
         capath = self.node.oget("cluster", "ca")
         if capath is None:
             capath = "system/sec/ca-" + self.node.cluster_name
         name, namespace, kind = split_path(capath)
         casec = factory("sec")(name,
                                namespace="system",
                                volatile=True,
                                log=self.log)
         if casec.exists():
             has_ca = True
             changes.append("ca=%s" % capath)
         else:
             print("no cluster CA defined. skip certificate generation.")
     if changes:
         self.set_multi(changes)
     if has_ca and "certificate" not in self.data_keys(
     ) and "private_key" in casec.data_keys():
         self.gen_cert()
Example #3
0
 def svc_ptr_record(self, qname):
     if not qname.endswith(PTR_SUFFIX):
         return []
     names = []
     ref = ".".join(reversed(qname[:-PTR_SUFFIX_LEN].split(".")))
     with shared.CLUSTER_DATA_LOCK:
         for nodename, node in shared.CLUSTER_DATA.items():
             status = node.get("services", {}).get("status", {})
             for path, svc in status.items():
                 name, namespace, kind = split_path(path)
                 if kind != "svc":
                     continue
                 if not namespace:
                     namespace = "root"
                 for rid, resource in status[path].get("resources",
                                                       {}).items():
                     addr = resource.get("info", {}).get("ipaddr")
                     if addr is None:
                         continue
                     if addr != ref:
                         continue
                     try:
                         hostname = resource.get(
                             "info",
                             {}).get("hostname").split(".")[0].lower()
                     except Exception:
                         hostname = None
                     gen_name = "%s.%s.%s.%s." % (name, namespace, kind,
                                                  self.cluster_name)
                     gen_name = gen_name.lower()
                     if hostname and hostname != name:
                         names.append("%s.%s" % (hostname, gen_name))
                     else:
                         names.append(gen_name)
     return names
Example #4
0
 def ca(self):
     capath = self.oget("DEFAULT", "ca")
     name, namespace, kind = split_path(capath)
     return factory("sec")(name,
                           namespace=namespace,
                           volatile=True,
                           node=self.node)
Example #5
0
 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)
Example #6
0
 def _install_data(self, kind):
     for data in self.data_data(kind):
         name, _, kind = split_path(data["obj"])
         obj = factory(kind)(name,
                             namespace=self.svc.namespace,
                             volatile=True,
                             node=self.svc.node)
         if not obj.exists():
             self.log.warning(
                 "referenced %s %s does not exist: "
                 "expected data %s can not be installed in the volume",
                 kind, name, data["key"])
             continue
         keys = obj.resolve_key(data["key"])
         if not keys and not is_glob(data["key"]):
             self.log.warning(
                 "%s %s has no key %s. "
                 "expected data can not be installed in the volume", kind,
                 name, data["key"])
             continue
         self.log.debug("install ./%s/%s/%s in %s", kind, name, data["key"],
                        data["path"])
         for key in keys:
             obj.install_key(key,
                             data["path"],
                             uid=self.uid,
                             gid=self.gid,
                             mode=self.octal_mode,
                             dirmode=self.octal_dirmode)
Example #7
0
 def rbac(self, nodename, thr=None, **kwargs):
     options = self.parse_options(kwargs)
     name, namespace, kind = split_path(options.path)
     if kind == "cfg":
         role = "guest"
     else:
         # sec, usr
         role = "admin"
     thr.rbac_requires(roles=[role], namespaces=[namespace], **kwargs)
Example #8
0
 def action(self, nodename, thr=None, **kwargs):
     options = self.parse_options(kwargs)
     name, namespace, kind = split_path(options.path)
     svc = factory(kind)(name=name, namespace=namespace, volatile=True)
     data = {
         "status": 0,
         "data": [res.rid for res in svc.get_resources("task") if res.confirmation],
     }
     return data
Example #9
0
    def a_records(self):
        data = self.get_cache("a")
        if data is not None:
            return data
        names = {}
        key = self.cache_key()
        for nodename in self.cluster_nodes:
            try:
                node = shared.CLUSTER_DATA[nodename]
            except KeyError:
                continue
            status = node.get("services", {}).get("status", {})
            for path, svc in status.items():
                name, namespace, kind = split_path(path)
                if kind != "svc":
                    continue
                if namespace:
                    namespace = namespace.lower()
                else:
                    namespace = "root"
                scaler_slave = svc.get("scaler_slave")
                if scaler_slave:
                    _name = name[name.index(".") + 1:]
                else:
                    _name = name

                zone = "%s.%s.%s." % (namespace, kind, self.cluster_name)
                qname = "%s.%s" % (_name, zone)
                if qname not in names:
                    names[qname] = set()

                local_zone = "%s.%s.%s.node.%s." % (namespace, kind, nodename,
                                                    self.cluster_name)
                local_qname = "%s.%s" % (_name, local_zone)
                if local_qname not in names:
                    names[local_qname] = set()

                for rid, resource in status.get(path, {}).get("resources",
                                                              {}).items():
                    addr = resource.get("info", {}).get("ipaddr")
                    if addr is None:
                        continue
                    hostname = resource.get("info", {}).get("hostname")
                    names[qname].add(addr)
                    names[local_qname].add(addr)
                    rname = self.unique_name(addr) + "." + qname
                    if rname not in names:
                        names[rname] = set()
                    names[rname].add(addr)
                    if hostname:
                        name = hostname.split(".")[0] + "." + qname
                        if name not in names:
                            names[name] = set()
                        names[name].add(addr)
        names.update(self.dns_a_records())
        self.set_cache(key, "a", names)
        return names
Example #10
0
    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)
Example #11
0
 def __init__(self, name):
     self.node_flag = os.path.join(Env.paths.pathvar, "node", "frozen")
     if name == "node":
         self.flag = self.node_flag
     else:
         name, namespace, kind = split_path(name)
         if namespace:
             self.flag = os.path.join(Env.paths.pathvar, "namespaces", namespace, kind, name, "frozen")
         else:
             self.flag = os.path.join(Env.paths.pathvar, kind, name, "frozen")
Example #12
0
 def a_records(self):
     data = self.get_cache("a")
     if data is not None:
         return data
     names = {}
     for nodename in self.cluster_nodes:
         try:
             node = shared.CLUSTER_DATA[nodename]
         except KeyError:
             continue
         status = node.get("services", {}).get("status", {})
         for path, svc in status.items():
             name, namespace, kind = split_path(path)
             if kind != "svc":
                 continue
             if namespace:
                 namespace = namespace.lower()
             else:
                 namespace = "root"
             scaler_slave = svc.get("scaler_slave")
             if scaler_slave:
                 _name = name[name.index(".") + 1:]
             else:
                 _name = name
             zone = "%s.%s.%s." % (namespace, kind, self.cluster_name)
             qname = "%s.%s" % (_name, zone)
             if qname not in names:
                 names[qname] = set()
             for rid, resource in status.get(path, {}).get("resources",
                                                           {}).items():
                 addr = resource.get("info", {}).get("ipaddr")
                 if addr is None:
                     continue
                 hostname = resource.get("info", {}).get("hostname")
                 names[qname].add(addr)
                 rname = self.unique_name(addr) + "." + qname
                 if rname not in names:
                     names[rname] = set()
                 names[rname].add(addr)
                 if hostname:
                     name = hostname.split(".")[0] + "." + qname
                     if name not in names:
                         names[name] = set()
                     names[name].add(addr)
     for i, ip in enumerate(shared.NODE.dns):
         try:
             dns = "%s.%s." % (shared.NODE.dnsnodes[i].split(".")[0],
                               self.cluster_name)
             names[dns] = set([ip])
         except IndexError:
             self.log.warning("dns (%s) and dnsnodes (%s) are not aligned"
                              "" % (shared.NODE.dns, shared.NODE.dnsnodes))
             break
     self.set_cache("a", names)
     return names
Example #13
0
 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)
Example #14
0
 def incompatible_claims(self, volume=None):
     if not volume:
         volume = self.volsvc
     volume_children_not_in_svc_parents = set()
     for e in volume.children:
         c1 = e + "@" + Env.nodename
         c2 = split_path(e)[0] + "@" + Env.nodename
         if c1 not in self.svc.parents and \
            c2 not in self.svc.parents:
             volume_children_not_in_svc_parents.add(e)
     return volume_children_not_in_svc_parents
Example #15
0
    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)
Example #16
0
    def rbac(self, nodename, thr=None, **kwargs):
        options = self.parse_options(kwargs)
        name, namespace, kind = split_path(options.path)

        if options.action in GUEST_ACTIONS:
            role = "guest"
        elif options.action in OPERATOR_ACTIONS:
            role = "operator"
        elif options.action in ADMIN_ACTIONS:
            role = "admin"
        else:
            role = "root"

        if options.action == "set":
            # load current config
            try:
                cf = shared.SERVICES[options.path].print_config_data()
            except Exception as exc:
                cf = {}

            # purge unwanted sections
            try:
                del cf["metadata"]
            except Exception:
                pass

            # merge changes in current config
            for buff in options.options.get("kw", []):
                k, v = buff.split("=", 1)
                if k[-1] in ("+", "-"):
                    k = k[:-1]
                k = k.strip()
                try:
                    s, k = k.split(".", 1)
                except Exception:
                    s = "DEFAULT"
                if s not in cf:
                    cf[s] = {}
                cf[s][k] = v

            # apply object create rbac to the amended config
            payload = {options.path: cf}
            errors = self.rbac_create_data(payload=payload, thr=thr, **kwargs)
            if errors:
                raise ex.HTTP(403, errors)
        else:
            thr.rbac_requires(roles=[role], namespaces=[namespace], **kwargs)

        if options.cmd:
            # compat, requires root
            kwargs["roles"] = ["root"]
            thr.rbac_requires(**kwargs)
Example #17
0
 def postinstall(self, key=None):
     """
     Refresh installed keys
     """
     changed_volumes = set()
     for path in list_services(namespace=self.namespace, kinds=["svc"]):
         name, _, _ = split_path(path)
         svc = factory("svc")(name, namespace=self.namespace, volatile=True, node=self.node, log=self.log)
         for res in svc.get_resources("volume"):
             if res.has_data(self.kind, self.path, key) and res._status() == core.status.UP:
                 installed = res._install_data(self.kind)
                 if installed:
                     changed_volumes.add(res.volsvc.path)
                 if res.volsvc.path in changed_volumes:
                     res.send_signals()
Example #18
0
 def dispatch_svcs(paths):
     data = {}
     for path in paths:
         try:
             _, _, kind = split_path(path)
         except ValueError:
             continue
         try:
             validate_kind(kind)
         except ValueError as exc:
             raise ex.Error(str(exc))
         try:
             data[kind].append(path)
         except KeyError:
             data[kind] = [path]
     return data
Example #19
0
 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)
Example #20
0
 def postinstall(self, key=None):
     """
     Refresh installed keys
     """
     for path in self.node.svcs_selector("*/svc/*",
                                         namespace=self.namespace,
                                         local=True):
         name, _, _ = split_path(path)
         svc = factory("svc")(name,
                              namespace=self.namespace,
                              volatile=True,
                              node=self.node,
                              log=self.log)
         for vol in svc.get_resources("volume"):
             if vol.has_data(self.kind, self.path,
                             key) and vol._status() == core.status.UP:
                 vol._install_data(self.kind)
Example #21
0
 def ptr_records(self):
     data = self.get_cache("ptr")
     if data is not None:
         return data
     names = {}
     key = self.cache_key()
     for nodename in self.cluster_nodes:
         try:
             node = shared.CLUSTER_DATA[nodename]
         except KeyError:
             continue
         status = node.get("services", {}).get("status", {})
         for path, svc in status.items():
             name, namespace, kind = split_path(path)
             if kind != "svc":
                 continue
             if not namespace:
                 namespace = "root"
             for rid, resource in status[path].get("resources", {}).items():
                 addr = resource.get("info", {}).get("ipaddr")
                 if addr is None:
                     continue
                 qname = "%s%s" % (
                     ".".join(reversed(addr.split("."))),
                     PTR_SUFFIX,
                 )
                 if qname not in names:
                     names[qname] = []
                 try:
                     hostname = resource.get(
                         "info", {}).get("hostname").split(".")[0].lower()
                 except Exception:
                     hostname = None
                 gen_name = "%s.%s.%s.%s." % (name, namespace, kind,
                                              self.cluster_name)
                 gen_name = gen_name.lower()
                 if hostname and hostname != name:
                     target = "%s.%s" % (hostname, gen_name)
                 else:
                     target = "%s" % gen_name
                 if target in names[qname]:
                     continue
                 names[qname].append(target)
     self.set_cache(key, "ptr", names)
     return names
Example #22
0
 def users(self, exclude=None):
     exclude = exclude or []
     users = []
     for child in self.children:
         if child in exclude:
             continue
         name, namespace, kind = split_path(child)
         obj = factory(kind)(name=name,
                             namespace=self.namespace,
                             volatile=True,
                             node=self.node)
         for res in obj.get_resources("volume"):
             if res.name != self.name:
                 continue
             if res.status() in (core.status.UP, core.status.STDBY_UP,
                                 core.status.WARN):
                 users.append(child)
     return users
Example #23
0
 def _data_status(self, kind):
     for data in self.data_data(kind):
         name, _, kind = split_path(data["obj"])
         obj = factory(kind)(name,
                             namespace=self.svc.namespace,
                             volatile=True,
                             node=self.svc.node)
         if not obj.exists():
             self.status_log(
                 "referenced %s %s does not exist: "
                 "expected data %s can not be installed in the volume" %
                 (kind, name, data["key"]), "warn")
             continue
         keys = obj.resolve_key(data["key"])
         if not keys and not is_glob(data["key"]):
             self.status_log(
                 "%s %s has no key %s. "
                 "expected data can not be installed in the volume" %
                 (kind, name, data["key"]), "warn")
Example #24
0
def format_instance(path,
                    idata,
                    mon_data=None,
                    discard_disabled=False,
                    nodename=None):
    name, namespace, kind = split_path(path)
    svc_notice = get_svc_notice(idata)

    tree = utilities.render.forest.Forest(
        separator=" ",
        widths=(
            (14, None),
            None,
            10,
            None,
        ),
    )
    node_name = tree.add_node()
    node_name.add_column(strip_path(path, os.environ.get("OSVC_NAMESPACE")),
                         color.BOLD)
    node_name.add_column()
    if "cluster" in idata:
        node_name.add_column(
            idata["cluster"].get("avail", "n/a"),
            STATUS_COLOR[idata["cluster"].get("avail", "n/a")])
    else:
        node_name.add_column()
    node_name.add_column(svc_notice)
    node_instances = node_name.add_node()
    node_instances.add_column("instances")
    add_instances(node_instances, path, nodename, mon_data)
    if nodename in service_nodes(path, mon_data):
        add_node_node(node_instances,
                      nodename,
                      idata,
                      mon_data,
                      discard_disabled=discard_disabled)
    add_parents(node_name, idata, mon_data, namespace)
    add_children(node_name, idata, mon_data, namespace)
    add_scaler_slaves(node_name, idata, mon_data, namespace)
    add_slaves(node_name, idata, mon_data, namespace)

    tree.out()
Example #25
0
    def action(self, nodename, thr=None, **kwargs):
        """
        Care with locks
        """
        thr.log_request("shutdown daemon", nodename, **kwargs)
        with shared.THREADS_LOCK:
            shared.THREADS["scheduler"].stop()
            mon = shared.THREADS["monitor"]
        if thr.stopped() or shared.NMON_DATA.status == "shutting":
            thr.log.info("already shutting")
            # wait for service shutdown to finish before releasing the dup client
            while True:
                if mon._shutdown:
                    break
                time.sleep(0.3)
            return {"status": 0}
        try:
            thr.set_nmon("shutting")
            mon.kill_procs()
            for path in shared.SMON_DATA:
                _, _, kind = split_path(path)
                if kind not in ("svc", "vol"):
                    continue
                thr.set_smon(path, local_expect="shutdown")
            self.wait_shutdown()

            # send a last status to peers so they can takeover asap
            mon.update_hb_data()

            mon._shutdown = True
            shared.wake_monitor("services shutdown done")
        except Exception as exc:
            thr.log.exception(exc)

        thr.log.info("services are now shutdown")
        while True:
            with shared.THREADS_LOCK:
                if not shared.THREADS["monitor"].is_alive():
                    break
            time.sleep(0.3)
        shared.DAEMON_STOP.set()
        return {"status": 0}
Example #26
0
    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))
Example #27
0
 def configure_volume(self,
                      volume,
                      size=None,
                      fmt=True,
                      access="rwo",
                      shared=False,
                      nodes=None,
                      env=None):
     if self.template is None:
         raise ex.Error("pool#%s.template is not set" % self.name)
     if not is_service(self.template):
         raise ex.Error("%s template volume not found" % self.template)
     name = self.default_disk_name(volume)
     tname, tnamespace, tkind = split_path(self.template)
     if tkind != "vol":
         raise ex.Error("%s template kind is not vol")
     svc = factory(tkind)(tname, tnamespace, volatile=True, node=self.node)
     config = svc.print_config_data()
     try:
         del config["DEFAULT"]["disable"]
     except KeyError:
         pass
     if "DEFAULT" not in config:
         config["DEFAULT"] = {}
     if "env" not in config:
         config["env"] = {}
     config["DEFAULT"]["pool"] = self.name
     config["DEFAULT"]["access"] = access
     if access in ("rox", "rwx"):
         config["DEFAULT"]["topology"] = "flex"
         config["DEFAULT"]["flex_min"] = 0
     if nodes:
         config["DEFAULT"]["nodes"] = nodes
     config["env"]["size"] = size
     if env:
         config["env"].update(env)
     self.node.install_svc_conf_from_data(volume.name, volume.namespace,
                                          volume.kind, config)
Example #28
0
    def action(self, nodename, thr=None, **kwargs):
        options = self.parse_options(kwargs)
        thr.log_request("drain node", nodename, **kwargs)
        thr.event("node_freeze", data={"reason": "drain"})
        thr.freezer.node_freeze()

        if thr.stopped() or shared.NMON_DATA.status in ("draining",
                                                        "shutting"):
            thr.log.info("already %s", shared.NMON_DATA.status)
            # wait for service shutdown to finish before releasing the dup client
            if options.wait:
                elapse = 0.0
                while True:
                    if shared.THREADS[
                            "monitor"]._shutdown or shared.NMON_DATA.status not in (
                                "draining", "shutting"):
                        break
                    if options.time and elapse > options.time:
                        return {"status": 1, "error": "timeout"}
                    time.sleep(0.3)
                    elapse += 0.3
            return {"status": 0}
        try:
            thr.set_nmon("draining")
            for path in shared.SMON_DATA:
                _, _, kind = split_path(path)
                if kind not in ("svc", "vol"):
                    continue
                thr.set_smon(path, local_expect="shutdown")
            if options.wait:
                try:
                    self.wait_shutdown(timeout=options.time)
                except ex.TimeOut:
                    return {"status": 1, "error": "timeout"}
        except Exception as exc:
            thr.log.exception(exc)

        return {"status": 0}
Example #29
0
    def action(self, nodename, thr=None, **kwargs):
        options = self.parse_options(kwargs)
        name, namespace, kind = split_path(options.path)

        if thr.get_service(options.path) is None and options.action not in ("create", "deploy"):
            thr.log_request("service action (%s not installed)" % options.path, nodename, lvl="warning", **kwargs)
            raise ex.HTTP(404, "%s not found" % options.path)
        if not options.action and not options.cmd:
            thr.log_request("service action (no action set)", nodename, lvl="error", **kwargs)
            raise ex.HTTP(400, "action not set")

        for opt in ("node", "daemon", "svcs", "service", "s", "parm_svcs", "local", "id"):
            if opt in options.options:
                del options.options[opt]
        for opt, ropt in (("jsonpath_filter", "filter"),):
            if opt in options.options:
                options.options[ropt] = options.options[opt]
                del options.options[opt]
        options.options["local"] = True
        pmod = importlib.import_module("commands.{kind}.parser".format(kind=kind))
        popt = pmod.OPT

        def find_opt(opt):
            for k, o in popt.items():
                if o.dest == opt:
                    return o
                if o.dest == "parm_" + opt:
                    return o

        if options.cmd:
            cmd = [options.cmd]
        else:
            cmd = [options.action]
            for opt, val in options.options.items():
                po = find_opt(opt)
                if po is None:
                    continue
                if val == po.default:
                    continue
                if val is None:
                    continue
                opt = po._long_opts[0] if po._long_opts else po._short_opts[0]
                if po.action == "append":
                    cmd += [opt + "=" + str(v) for v in val]
                elif po.action == "store_true" and val:
                    cmd.append(opt)
                elif po.action == "store_false" and not val:
                    cmd.append(opt)
                elif po.type == "string":
                    opt += "=" + val
                    cmd.append(opt)
                elif po.type == "integer":
                    opt += "=" + str(val)
                    cmd.append(opt)

        fullcmd = Env.om + ["svc", "-s", options.path] + cmd
        thr.log_request("run 'om %s %s'" % (options.path, " ".join(cmd)), nodename, **kwargs)
        if options.sync:
            proc = Popen(fullcmd, stdout=PIPE, stderr=PIPE, stdin=None, close_fds=True)
            out, err = proc.communicate()
            try:
                result = json.loads(out)
            except Exception:
                result = {
                    "status": 0,
                    "data": {
                        "out": bdecode(out),
                        "err": bdecode(err),
                        "ret": proc.returncode,
                    },
                }
        else:
            import uuid
            session_id = str(uuid.uuid4())
            env = {}
            env.update(os.environ)
            env["OSVC_PARENT_SESSION_UUID"] = session_id
            proc = Popen(fullcmd, stdin=None, close_fds=True, env=env)
            thr.push_proc(proc)
            result = {
                "status": 0,
                "data": {
                    "pid": proc.pid,
                    "session_id": session_id,
                },
                "info": "started %s action %s" % (options.path, " ".join(cmd)),
            }
        return result
Example #30
0
    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)