Exemple #1
0
 async def do(self, args):
     await self.root.setup(self)
     etc = self.root.etcd
     path = '/device'
     if not args:
         raise CommandError("You need to specify a device.")
     arg = args.pop(0)
     types = EtcTypes()
     Device.types(types)
     try:
         t = await etc.tree('/'.join((path, arg, DEV)),
                            types=types,
                            create=False)
     except KeyError:
         raise CommandError("Device '%s' not found." % (arg, ))
     if args:
         args = ' '.join(args)
         if args == '-':
             if self._nl:
                 args = sys.stdin.read().rstrip('\n')
             else:
                 args = sys.stdin.readline().rstrip('\n')
         await t.set(self._attr, args)
         if self.root.verbose > 1:
             print("Location set.", file=self.stdout)
     elif self._attr in t:
         print(t[self._attr], file=self.stdout)
     elif self.root.verbose:
         print(self._attr.ucfirst() + " not yet set.", file=sys.stderr)
         return 1
Exemple #2
0
 async def do(self, args):
     t = await self.setup(meta=False)
     if not args:
         if not cmd.root.cfg['testing']:
             raise CommandError("You can't delete everything.")
         args = t
     for k in args:
         try:
             task = await t.subdir(k, name=TASK, create=False)
         except KeyError:
             raise CommandError("%s: does not exist" % k)
         if self.root.verbose:
             print("%s: deleted" % k, file=self.stdout)
         rec = None
         while True:
             p = task._parent
             if p is None: break
             p = p()
             if p is None: break
             if p is task: break
             try:
                 await task.delete(recursive=rec)
             except etcd.EtcdDirNotEmpty:
                 if rec:
                     raise
                 break
             rec = False
             task = p
Exemple #3
0
 async def do(self,args):
     t = await self.setup()
     if not args:
         if not cmd.root.cfg['testing']:
             raise CommandError("You can't delete everything.")
         if not self.options.recursive:
             raise CommandError("You can't delete everything non-recursively.")
         await t.delete(recursive=True)
         return
     for k in args:
         try:
             dev = await t.subdir(k,name=DEV, create=False)
         except KeyError:
             raise CommandError("%s: does not exist"%k)
         if self.root.verbose:
             print("%s: deleted"%k, file=self.stdout)
         rec=self.options.recursive
         while True:
             p = dev._parent
             if p is None: break
             p = p()
             if p is None: break
             if p is t: break
             try:
                 await dev.delete(recursive=rec)
             except etcd.EtcdDirNotEmpty:
                 break
             rec=False
             dev = p
Exemple #4
0
 async def do(self, args):
     if not args:
         raise CommandError("Not specifying values to %s makes no sense." %
                            ("delete" if self.delete else "add/update"))
     etc = await self.root._get_etcd()
     retval = 0
     if self.delete:
         if not self.create:
             raise CommandError(
                 "You can't update and delete at the same time.")
         for a in args:
             pa = a.replace('.', '/')
             kw = {}
             if self.modified:
                 kw['prevIndex'] = self.modified
             if self.previous:
                 kw['prevValue'] = self.previous
             try:
                 await etc.delete('/' + pa, recursive=True, **kw)
             except etcd.EtcdCompareFailed:
                 logger.fatal("Bad modstamp: " + a)
                 retval = 1
             except etcd.EtcdKeyNotFound:
                 logger.info("Key already deleted: " + a)
     else:
         for a in args:
             a, v = a.split('=', 1)
             pa = a.replace('.', '/')
             create = self.create
             try:
                 kw = {}
                 if self.modified:
                     kw['index'] = self.modified
                     create = False
                 if self.previous:
                     kw['prev'] = self.previous
                     create = False
                 if v:
                     kw['value'] = v
                 if self.append:
                     kw['append'] = True
                     create = True
                 r = await etc.set('/' + pa, create=create, **kw)
                 if self.append:
                     print(r.key.rsplit('/', 1)[1], file=self.stdout)
             except etcd.EtcdCompareFailed:
                 logger.error("Bad modstamp: " + a)
                 retval = 1
             except etcd.EtcdAlreadyExist:
                 logger.error("Entry exists: " + a)
                 retval = 1
     return retval
Exemple #5
0
    async def do(self, args):
        if not args:
            raise CommandError("Not specifying values to %s makes no sense." %
                               ("delete" if self.delete else "add/update"))
        etc = await self.root._get_etcd()
        retval = 0
        if len(args) < 2 or '=' not in args[-1]:
            raise SyntaxError("Usage: … path/to/device input/name entry=value")
        p = p1 = '/' + '/'.join(DEV_DIR) + '/' + args.pop(0).replace(
            '.', '/') + '/' + DEV

        import pdb
        pdb.set_trace()
        for a in args:
            if '=' not in a:
                p = p1 + '/' + a.replace('.', '/')
                continue
            a, v = a.split('=', 1)
            pa = p + '/' + a.replace('.', '/')
            try:
                if v == '' and self.delete:
                    r = await etc.delete(pa)
                else:
                    r = await etc.set(pa, value=v, ext=True)
            except etcd.EtcdKeyNotFound:
                logger.info("Key already deleted: " + a)
            except etcd.EtcdCompareFailed:
                logger.error("Bad modstamp: " + a)
                retval = 1
            except etcd.EtcdAlreadyExist:
                logger.error("Entry exists: " + a)
                retval = 1
        return retval
Exemple #6
0
    async def do(self, args):
        tree = await self.root._get_tree()
        t = await self.setup(meta=True)
        if args:
            objs = []
            for a in args:
                m = import_string(a)
                if isinstance(m, py_types.ModuleType):
                    from moat.script.util import objects
                    n = 0
                    for c in objects(m,
                                     Task,
                                     filter=lambda x: getattr(
                                         x, 'taskdef', None) is not None):
                        await t.add_task(c, force=self.force)
                        n += 1
                    if self.root.verbose > (1 if n else 0):
                        print("%s: %s command%s found." %
                              (a, n if n else "no", "" if n == 1 else "s"),
                              file=self.stdout)
                else:
                    if not isinstance(m, Task):
                        raise CommandError("%s is not a task" % a)
                    await t.add_task(m, force=self.force)
        else:
            for c in task_types():
                await t.add_task(c, force=self.force)

            r = await tree.subdir(*TASKSCAN_DIR)
            from moat.task.collect import Collector
            await r.add_task(path=(),
                             taskdef=Collector.taskdef,
                             force=self.force)

        await t.wait()
Exemple #7
0
    async def do(self,args):
        t = await self.setup()
        if args:
            dirs = []
            for a in args:
                try:
                    dirs.append(await t.subdir(a, create=False))
                except KeyError:
                    raise CommandError("'%s' does not exist"%(a,))
        else:
            dirs = [t]
        for tt in dirs:
            async for dev in tt.tagged(DEV, depth=self.options.this):
                path = dev.path[len(DEV_DIR):-1]
                if self.root.verbose == 2:
                    print('*','/'.join(path), sep='\t',file=self.stdout)
                    for k,v in r_show(dev,''):
                        print(k,v, sep='\t',file=self.stdout)

                elif self.root.verbose > 1:
                    dump({'/'.join(path):r_dict(dict(dev))}, stream=self.stdout)
                else:
                    path = '/'.join(path)
                    name = dev.get('name','-')
                    val = dev.get('value','-')
                    if name == path:
                        name = "-"
                    print(path,name,val, sep='\t',file=self.stdout)
Exemple #8
0
    async def do(self, args):
        if self.root.cfg['config'].get('testing', False):
            print("NOTE: this is a test configuration.", file=sys.stderr)
        else:  # pragma: no cover ## not doing the real thing here
            print("WARNING: this is NOT a test.", file=sys.stderr)
            time.sleep(3)

        if args:
            return (await super().do(args))

        res = 0
        for c in self.subCommandClasses:
            if c.summary is None:
                continue
            if self.root.verbose > 1:
                print("Checking:", c.name)
            c = c(parent=self)
            try:
                res = (await c.do(args) or 0)
            except Exception as exc:  # pragma: no cover
                if self.root.verbose > 1:
                    import traceback
                    traceback.print_exc(file=sys.stderr)
                    return 9
                raise CommandError("%s failed: %s" % (c.name, repr(exc)))
            else:
                if res:
                    print("Error. Stopped test run.", file=sys.stderr)
                    return res
        if self.root.verbose:
            print("All tests done.", file=self.stdout)
        return res
Exemple #9
0
 def handleOptions(self):
     opts = self.options
     if (opts.delete or opts.modified or opts.previous) and opts.append:
         raise CommandError("Conflicting arguments")
     self.delete = opts.delete
     self.modified = opts.modified
     self.previous = opts.previous
     self.append = opts.append
     self.create = not opts.update
Exemple #10
0
 async def do(self, args):
     if not self.root.cfg['config'].get('testing',False) or \
        len(args) != 2 or " ".join(args) != "me hardeR":
         raise CommandError("You're insane.")
     etc = await self.root._get_etcd()
     self.log.fatal("Erasing your etcd data in three seconds.")
     time.sleep(3)
     await etc.delete("/", recursive=True)
     self.log.warn("All gone.")
     return
Exemple #11
0
    async def do(self,args):
        t = await self.setup()

        try:
            data = {}
            name=""

            webpath = args[0].rstrip('/').lstrip('/')
            if webpath == "":
                raise CommandError("Empty web entry path?")
            if webpath[0] == ':' or '/:' in webpath:
                raise CommandError("Don't add the tag")

            p=1
            while p < len(args):
                try:
                    k,v = args[p].split('=')
                except ValueError:
                    break
                p += 1
                data[k] = v
            descr = " ".join(args[p:])
        except IndexError:
            raise CommandError("Missing command parameters")
        finally:
            pass

        try:
            web = await t.subdir(webpath, name=WEBSERVER, create=not self._update)
        except KeyError:
            raise CommandError("Web item '%s' not found." % webpath)
        if descr:
            await web.set('descr', descr, sync=False)
        if data:
            for k,v in data.items():
                if v == "":
                    try:
                        await web.delete(k, sync=False)
                    except KeyError:
                        pass
                else:
                    await web.set(k,v, sync=False, ext=True)
Exemple #12
0
	async def do(self,args):
		await self.root.setup(self)
		if len(args) < 2:
			raise CommandError("Usage: … add ‹name› ‹host› [‹port›]")
		name = args[0]
		if ':' in name or '/' in name:
			raise CommandError("The service name can't contain colons or slashes.")
		host = args[1]
		try:
			if args[2] == '-':
				port = 4304
			else:
				port = int(args[2])
		except IndexError:
			port = 4304
		except ValueError:
			raise CommandError("The port must be an integer")
		else:
			if port<1 or port>65534:
				raise CommandError("The port must be positive and <65535")

		try:
			t = await self.root.tree.subdir('bus','onewire',name, create=not self.update)
			await t.subdir('bus')
		except etcd.EtcdAlreadyExist:
			raise CommandError("Host '%s' exists. Use '-u' or choose a different name." % name)
		except etcd.EtcdKeyNotFound:
			raise CommandError("Host '%s' does not exist. Drop '-u' or choose an existing name." % name)
		await t.set('server',{'host':host,'port':port})

		if len(args) > 3:
			await t.set('info',' '.join(args[3:]))
		if self.root.verbose > 1:
			print(name, "updated" if self.update else "created", file=self.stdout)
Exemple #13
0
    async def do(self, args):
        tree = await self.root._get_tree()

        if not len(args):
            args = ("", )
        else:
            if len(args) > 1 and self.options.watch:
                raise CommandError("You can only watch one node. Sorry.")
        for a in args:
            a = tuple(x for x in a.split('/') if x != '')
            try:
                d = await tree.lookup(*a)
            except KeyError:
                print("Node '%s' not found" % (a, ), file=sys.stderr)
                continue
            try:
                coll = d.task_monitor
            except AttributeError:
                print("Node '%s' does not have tasks" % (d, ), file=sys.stderr)
                continue

            def show(r):
                if len(r) > 1:
                    r1 = r[1]
                    if not isinstance(r1, str):
                        r1 = '/'.join(r1)
                if r[0] == 'add':
                    print("Task:" + r1,
                          'at',
                          '/'.join(r[2]),
                          *r[3:],
                          file=self.stdout)
                elif r[0] == 'drop':
                    print("Delete", r1, *r[2:], file=self.stdout)
                elif r[0] == 'scan':
                    print("Subtask", r1, *r[2:], file=self.stdout)
                elif r[0] == 'watch':
                    print('---', file=self.stdout)
                    if not self.options.watch:
                        raise StopIteration
                else:
                    raise RuntimeError("Unknown response: " + repr(r))

            if hasattr(coll, '__aiter__'):
                async for r in coll:
                    try:
                        show(r)
                    except StopIteration:
                        break
            else:
                for r in coll:
                    show(r)
Exemple #14
0
    async def do(self, args):
        t = await self.setup()
        tree = await self.root._get_tree()
        t2 = await tree.subdir(TASKDEF_DIR)

        if args:
            objs = []
            for a in args:
                m = import_string(a)
                if isinstance(m, py_types.ModuleType):
                    try:
                        syms = m.__all__
                    except AttributeError:
                        syms = dir(m)
                    n = 0
                    for c in syms:
                        c = getattr(m, c, None)
                        if isinstance(c, type) and issubclass(
                                c, BaseModule) and c.prefix is not None:
                            objs.append(c)
                            n += 1
                    if self.root.verbose > (1 if n else 0):
                        print("%s: %s module%s found." %
                              (a, n if n else "no", "" if n == 1 else "s"),
                              file=self.stdout)

                    if self.tasks:
                        n = 0
                        for c in objects(m,
                                         Task,
                                         filter=lambda x: getattr(
                                             x, 'taskdef', None) is not None):
                            await t2.add_task(c, force=self.force)
                            n += 1
                        if self.root.verbose > (1 if n else 0):
                            print("%s: %s command%s found." %
                                  (a, n if n else "no", "" if n == 1 else "s"),
                                  file=self.stdout)

                else:
                    if not isinstance(m, BaseModule):
                        raise CommandError("%s is not a task" % a)
                    objs.append(m)
        else:
            objs = modules()

        tasks = await t.root.subdir(TASKDEF_DIR)
        for obj in objs:
            await t.add_module(obj, force=self.force)
            for ta in obj.task_types():
                await tasks.add_task(ta, force=self.force)
        await t.wait()
Exemple #15
0
 async def do(self, args):
     import moat.util  # side effect: loads YAML representers
     from yaml import dump
     if args:
         try:
             for n, a in enumerate(args):
                 if n:
                     print("---", file=self.stdout)
                 c = self.root.cfg
                 for aa in a.split('.'):
                     c = c[aa]
                 dump(c, stream=self.stdout)
         except KeyError:
             raise CommandError("Key %s does not exist" % (repr(a), ))
     else:
         dump(self.root.cfg, stream=self.stdout)
Exemple #16
0
    async def do(self, args):
        t = await self.setup()
        if args:
            dirs = []
            for a in args:
                tt = t
                try:
                    for k in a.split('/'):
                        if k:
                            tt = tt._get(k)
                    dirs.append(tt)
                except KeyError:
                    print("Module '%s' not known" % (a, ), file=sys.stderr)
        else:
            if not cmd.root.cfg['testing']:
                raise CommandError("You can't delete everything.")
            dirs = (t)

        for k in dirs:
            t = await k
            k = t.path
            rec = True
            while True:
                p = t._parent
                if p is None: break
                p = p()
                if p is None or p is t: break
                try:
                    await t.delete(recursive=rec)
                except etcd.EtcdDirNotEmpty:
                    if rec:
                        raise
                    break
                if isinstance(t, MoatLoaderDir):
                    try:
                        t2 = t.root.lookup(*TASKDEF_DIR, self.name)
                    except KeyError:
                        pass
                    else:
                        await t2.delete(recursive=True)
                rec = False
                t = p
            if self.root.verbose:
                print("%s: deleted" % '/'.join(k), file=self.stdout)
Exemple #17
0
 async def do(self,args):
     t = await self.setup()
     if args:
         if self.options.all:
             raise CommandError("Arguments and '-a' are mutually exclusive")
         dirs = []
         for a in args:
             dirs.append(await t.subdir(a, create=False))
         verbose = True
     else:
         dirs = [t]
         verbose = self.options.all
     for tt in dirs:
         async for web in tt.tagged(WEBSERVER):
             path = web.path[len(WEBSERVER_DIR):-1]
             if verbose:
                 dump({path: r_dict(dict(web))}, stream=self.stdout)
             else:
                 print('/'.join(path), web.get('host','-'), web.get('port',80), web.get('default','default'), web.get('descr',''), sep='\t',file=self.stdout)
Exemple #18
0
	async def do(self,args):
		await self.root.setup(self)
		etc = self.root.etcd
		if not args:
			if not cmd.root.cfg['testing']:
				raise CommandError("You can't delete everything.")
			args = []
			res = etc.get('/bus/onewire')
			for r in res.children:
				args.append(r.name.rsplit('/',1)[1])
		for k in args:
			try:
				await etc.delete('/bus/onewire/'+k, recursive=True)
			except etcd.EtcdKeyNotFound:
				if self.root.verbose:
					print("%s: not known"%k, file=sys.stderr)
			else:
				with suppress(etcd.EtcdKeyNotFound):
					await etc.delete('/task/onewire/'+k, recursive=True)
				with suppress(etcd.EtcdKeyNotFound):
					await etc.delete('/task/moat/scan/bus/onewire/'+k, recursive=True)
Exemple #19
0
 async def do(self, args):
     t = await self.setup(meta=True)
     if args:
         if self.options.all:
             raise CommandError("Arguments and '-a' are mutually exclusive")
         dirs = []
         for a in args:
             dirs.append(await t.subdir(a, create=False))
         verbose = True
     else:
         dirs = [t]
         verbose = self.options.all
     for tt in dirs:
         async for task in tt.tagged(TASKDEF):
             path = task.path[len(TASKDEF_DIR):-1]
             if verbose:
                 dump({path: r_dict(dict(task))}, stream=self.stdout)
             else:
                 print('/'.join(path),
                       task.get('summary', task.get('descr', '??')),
                       sep='\t',
                       file=self.stdout)
Exemple #20
0
    async def do(self,args):
        tree = await self.root._get_tree()
        t = await self.setup(meta=True)
        if args:
            objs = []
            for a in args:
                m = import_string(a)
                if isinstance(m,types.ModuleType):
                    from moat.script.util import objects
                    n = 0
                    for c in objects(m, WebdefDir, filter=lambda x:getattr(x,'name',None) is not None):
                        await t.add_webdef(c, force=self.force)
                        n += 1
                    if self.root.verbose > (1 if n else 0):
                        print("%s: %s webdef%s found." % (a,n if n else "no", "" if n==1 else "s"), file=self.stdout)
                else:
                    if not isinstance(m,WebdefDir):
                        raise CommandError("%s is not a web definition"%a)
                    await t.add_webdef(m, force=self.force)
        else:
            for c in webdefs():
                await t.add_webdef(c, force=self.force)

        await t.wait()
Exemple #21
0
 async def do(self, args):
     td = await self.setup(meta=True)
     if not args:
         if not cmd.root.cfg['testing']:
             raise CommandError("You can't delete everything.")
         args = td.tagged(TASKDEF)
     for k in args:
         t = await td.subdir(k, name=TASKDEF, create=False)
         if self.root.verbose:
             print("%s: deleted" % k, file=self.stdout)
         rec = True
         while True:
             p = t._parent
             if p is None: break
             p = p()
             if p is None or p is t: break
             try:
                 await t.delete(recursive=rec)
             except etcd.EtcdDirNotEmpty:
                 if rec:
                     raise
                 break
             rec = False
             t = p
Exemple #22
0
    def handleOptions(self):
        opts = self.options
        self.verbose = opts.verbose

        paths = []
        if opts.files:
            for f in opts.files:
                paths.extend(glob.glob(f))

        if not paths:  # pragma: no cover ## not while testing!
            if 'MOAT_CFG' in os.environ:
                paths.append(os.environ['MOAT_CFG'])
            elif os.path.exists(DEFAULT_CFG):
                paths.append(DEFAULT_CFG)

        self.cfg = {'config': {}}
        if not opts.no_default:
            r_update(self.cfg['config'], DEFAULT_CONFIG)
            r_update(self.cfg['config'], QBROKER_DEFAULT_CONFIG)
        for p in paths:
            with open(p) as f:
                cfg = yaml.safe_load(f)
                r_update(self.cfg, cfg)
        if opts.opts:
            for o in opts.opts:
                k, v = o.split('=', 1)
                oc = None
                c = self.cfg
                for kk in k.split('.'):
                    oc = c
                    ok = kk
                    c = c.setdefault(kk, {})
                oc[ok] = v
        #logging.basicConfig(stream=logfile,level=(logging.ERROR,logging.WARNING,logging.INFO,logging.INFO,logging.DEBUG)[min(self.verbose,4)])
        lcfg = self.cfg['config'].setdefault('logging', {'version': 1})
        hd = lcfg.setdefault('root', {}).setdefault('handlers', [])
        if opts.logto:
            if 'logfile' not in hd:
                hd.append('logfile')
            lh = lcfg['handlers'].setdefault('logfile', {
                'level': 'logging.DEBUG',
                'formatter': 'std',
            })
            lh['class'] = 'logging.FileHandler'
            lh['filename'] = opts.logto
        fmt = lcfg.setdefault('formatters', {})
        fmt.setdefault('std', {'format': '%(levelname)s:%(name)s:%(message)s'})
        fmt.setdefault('stderr', {'format': '%(message)s'})

        if opts.verbose:
            if 'stderr' not in hd:
                hd.append('stderr')
        else:
            if 'stderr' in hd:
                hd.remove('stderr')
        lh = lcfg.setdefault('handlers',
                             {}).setdefault('stderr', {'formatter': 'stderr'})
        lh['class'] = 'logging.StreamHandler'
        lh['stream'] = sys.stderr
        lh['level'] = ('ERROR', 'ERROR', 'WARNING', 'INFO', 'INFO',
                       'DEBUG')[min(self.verbose, 5)]

        from logging.config import dictConfig
        lcfg['disable_existing_loggers'] = False
        dictConfig(lcfg)
        logging.captureWarnings(True)

        self.app = self.cfg['config'].get('app', None)

        # Rather than enumerate IP addresses, this is the quick&only-somewhat-dirty way
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8',
                   53))  # connecting to a UDP address doesn't send packets
        addr = s.getsockname()[0]
        s.close()
        if self.app is None:
            addr = socket.getfqdn(addr)
            addr = addr.split('.')
            if len(addr) < 3:  # pragma: no cover
                raise CommandError(
                    "You need to fix your FQDN ('%s'), or use the '-a' option."
                    % ".".join(addr))
            #addr.reverse()
            self.host = ".".join(addr)
Exemple #23
0
 async def do(self, args):
     c = self.root.cfg
     try:
         c = c['config']
     except KeyError:  # pragma: no cover
         raise CommandError("config: missing 'config' entry")
Exemple #24
0
    async def do(self,args):
        try:
            data = {}
            webdefpath=""
            name=""
            p=0

            webpath = args[p].rstrip('/').lstrip('/')
            if webpath == "":
                raise CommandError("Empty web entry path?")
            if webpath[0] == ':' or '/:' in webpath:
                raise CommandError("Don't add the tag")
            p+=1

            if not self._update:
                webdefpath = args[p].rstrip('/').lstrip('/')
                if webdefpath == "":
                    raise CommandError("Empty web definition path?")
                if webdefpath[0] == ':' or '/:' in webdefpath:
                    raise CommandError("Don't add the tag")
                p+=1
            while p < len(args):
                try:
                    k,v = args[p].split('=')
                except ValueError:
                    break
                p += 1
                if k == "name":
                    name = v
                else:
                    data[k] = v
            if not self._update:
                args[p] # raises IndexError if nothing is left
            descr = " ".join(args[p:])
        except IndexError:
            raise CommandError("Missing command parameters")
        t = await self.setup(meta=False)
        if not self._update:
            try:
                td = await self.setup(meta=True)
                webdef = await td.subdir(webdefpath,name=WEBDEF, create=False)
            except KeyError:
                raise CommandError("Web def '%s' not found" % webdefpath)

        try:
            web = await t.subdir(webpath,name=WEBDATA, create=not self._update)
        except KeyError:
            raise CommandError("Web item '%s' not found." % webpath)
        if not self._update:
            await web.set('def', webdefpath, sync=False)
        if name:
            await web.set('name', name, sync=False)
        if descr:
            await web.set('descr', descr, sync=False)
        if data:
            for k,v in data.items():
                if v == "":
                    try:
                        await web.delete(k, sync=False)
                    except KeyError:
                        pass
                else:
                    await web.set(k,v, sync=False)
Exemple #25
0
    async def do(self, args):
        c = self.root.cfg['config']
        try:
            c = c['etcd']
        except KeyError:
            raise CommandError("config: missing 'etcd' section")
        for k in ('host', 'port', 'root'):
            if k not in c:
                raise CommandError("config.etcd: missing '%s' entry" %
                                   k)  # pragma: no cover

        retval = 0
        etc = await self.root._get_etcd()
        tree = await self.root._get_tree()
        log = logging.getLogger(__name__ + ".etcd")
        show = log.info if self.parent.fix else log.warning

        try:
            s = None
            s = await etc.tree('/config')
            await s.subdir('run', create=False)
        except KeyError:
            show("/config/run created.")
            if self.parent.fix:
                await s.subdir('run', create=True)
            else:
                retval += 1
        finally:
            if s is not None:
                await s.close()

        stats = set(("ok", "warn", "error", "fail"))
        s = await etc.tree("/status")
        try:
            if "run" not in s:
                show("missing 'run' entry")
                if self.parent.fix:
                    await s.set("run", dict())  # pragma: no cover
                else:
                    retval += 1
            if "error" not in s:
                show("missing 'error' entry")
                if self.parent.fix:
                    await s.set("error", dict())
                else:
                    retval += 1

            await s.wait()
            if not self.root.cfg['config'].get('testing', False):
                return

            # The next part is test environment only
            try:
                t = self.Task_do3(self, "test/do_3")
                await t
            except RuntimeError as exc:
                pass
            else:
                raise RuntimeError(
                    "Error did not propagate")  # pragma: no cover
            run_state = await _run_state(tree, ('test', 'do_3'))
            if 'running' in run_state:
                raise RuntimeError(
                    "Procedure end 2 did not take")  # pragma: no cover
            await s.wait()
            assert run_state['stopped'] > run_state['started'], (
                run_state['stopped'], run_state['started'])
            assert run_state['state'] == "error", run_state['state']

            try:
                t = self.Task_do4(self, "test/do_4", _ttl=3, _refresh=10)
                await t
            except JobMarkGoneError:
                pass
            else:
                raise RuntimeError(
                    "Cancellation ('running' marker gone) did not propagate"
                )  # pragma: no cover
            run_state = await _run_state(tree, ('test', 'do_4'))
            assert 'running' not in run_state
            await s.wait()
            assert run_state['stopped'] > run_state['started'], (
                run_state['stopped'], run_state['started'])
            assert run_state['state'] == "fail", run_state['state']

            logger.error(
                "The following 'Job is already running' message is part of the test."
            )
            global _do2_running
            _do2_running = False
            dt2 = self.Task_do2(self, "test/do_2", {})
            await s.wait()
            dt2.run_state = run_state = await _run_state(
                tree, ('test', 'do_2'))
            t1 = time.time()
            while True:
                if _do2_running:
                    break
                await asyncio.sleep(0.1, loop=self.root.loop)
                if time.time() - t1 > 10:
                    import pdb
                    pdb.set_trace()
                    raise RuntimeError("do2 didn't run")

            dt2a = self.Task_do2(self, "test/do_2", {})
            try:
                await dt2a
            except JobIsRunningError as exc:
                assert exc.args[0] == "test/do_2", exc
            else:
                raise RuntimeError("Dup run didn't")  # pragma: no cover
            await dt2
            if 'running' in run_state:
                raise RuntimeError(
                    "Procedure end did not take")  # pragma: no cover
            await s.wait()
            assert run_state['stopped'] > run_state['started'], (
                run_state['stopped'], run_state['started'])
            assert run_state['state'] == "ok", run_state['state']

            try:
                errs = await etc.read("/status/error")
            except etcd.EtcdKeyNotFound:
                if self.parent.fix:
                    raise RuntimeError(
                        "Creating /status/error did not take. Duh?"
                    )  # pragma: no cover ## hopefully
                # otherwise it's not there and there's nothing to do
            else:
                pass

        finally:
            await s.close()
        return retval
Exemple #26
0
    async def do(self,args):
        try:
            data = {}
            name=""
            p=0

            devpath = args[p].rstrip('/').lstrip('/')
            if devpath == "":
                raise CommandError("Empty dev entry path?")
            if devpath[0] == ':' or '/:' in devpath:
                raise CommandError("Don't add the tag")
            p+=1

            if not self._update:
                typepath = args[p].rstrip('/').lstrip('/')
                if typepath == "":
                    raise CommandError("Empty type path?")
                if typepath[0] == ':' or '/:' in typepath:
                    raise CommandError("Don't add the tag")
                p+=1
            while p < len(args):
                try:
                    k,v = args[p].split('=')
                except ValueError:
                    break
                p += 1
                if k == "name":
                    name = v
                else:
                    data[k] = v
            if not self._update:
                args[p] # raises IndexError if nothing is left
            descr = " ".join(args[p:])
        except IndexError:
            raise CommandError("Missing command parameters")
        t = await self.setup()
        if not self._update:
            try:
                td = await t.root.lookup(TYPEDEF_DIR)
                td = await td.lookup(typepath, name=TYPEDEF)
            except KeyError:
                raise CommandError("type '%s' not found" % (typepath,))

        try:
            dev = await t.subdir(devpath,name=DEV, create=not self._update)
        except KeyError:
            raise CommandError("Device item '%s' not found." % (devpath,))
        if not self._update:
            await dev.set('type', typepath, sync=False)
        if name:
            await dev.set('name', name, sync=False)
        if descr:
            await dev.set('descr', descr, sync=False)
        if data:
            d = await dev.subdir('data', create=None)
            for k,v in data.items():
                if k.startswith("input/") or k.startswith("output/"):
                    dx = dev
                else:
                    dx = d
                if v == "":
                    try:
                        await dx.delete(k, sync=False)
                    except KeyError:
                        pass
                else:
                    await dx.set(k.split('/'),v, sync=False, ext=True)
Exemple #27
0
    async def do(self, args):
        t = await self.setup(meta=self._def)
        if self._def and self.options.is_global:
            if self.options.delete:
                raise CommandError("You cannot delete global parameters.")
            data = self.root.etc_cfg['run']
        elif not args:
            if self.options.delete:
                raise CommandError("You cannot delete all parameters.")

            async for task in t.tagged(self.TAG, depth=self.DEPTH):
                path = task.path[len(self.DIR):-1]
                for k in self._VARS:
                    if k in task:
                        print('/'.join(path),
                              k,
                              task[k],
                              sep='\t',
                              file=self.stdout)
            return
        else:
            name = args.pop(0)
            try:
                data = await t.subdir(name,
                                      name=self.TAG,
                                      create=None if self._make else False)
            except KeyError:
                raise CommandError("Task definition '%s' is unknown." % name)

        if self.options.delete:
            if not args:
                args = self._VARS
            for k in args:
                if k in data:
                    if self.root.verbose:
                        print("%s=%s (deleted)" % (k, data[k]),
                              file=self.stdout)
                    await data.delete(k)
        elif len(args) == 1 and '=' not in args[0]:
            print(data[args[0]], file=self.stdout)
        elif not len(args):
            for k in self._VARS:
                if k in data:
                    print(k, data[k], sep='\t', file=self.stdout)
        else:
            while args:
                k = args.pop(0)
                try:
                    k, v = k.split('=', 1)
                except ValueError:
                    if k not in self._VARS:
                        raise CommandError("'%s' is not a valid parameter." %
                                           k)
                    print(k, data.get(k, '-'), sep='\t', file=self.stdout)
                else:
                    if k not in self._VARS:
                        raise CommandError("'%s' is not a valid parameter." %
                                           k)
                    if self.root.verbose:
                        if k not in data:
                            print("%s=%s (new)" % (k, v), file=self.stdout)
                        elif str(data[k]) == v:
                            print("%s=%s (unchanged)" % (k, v),
                                  file=self.stdout)
                        else:
                            print("%s=%s (was %s)" % (k, v, data[k]),
                                  file=self.stdout)
                    await data.set(k, v, ext=True)
Exemple #28
0
    async def do(self, args):
        from yaml import safe_dump
        from moat.dev import DEV_DIR, DEV
        from moat.dev.base import _SOURCES
        tree = await self.root._get_tree()
        tree = tree.lookup(DEV_DIR)
        if self.options.list and self.options.show:
            raise CommandError("'-s' and '-l' are mutually exclusive")
        if self.options.list or self.options.show or len(args) < 2:
            if len(args) == 0:
                args = ((), )
            for a in args:
                try:
                    t = await tree.lookup(a)
                    if len(args) == 1 and DEV in t and not self.options.list:
                        self.options.show = True
                    if self.options.show and DEV not in t:
                        print("'%s': not a device.'" % (a, ), file=sys.stderr)
                        continue
                    if not self.options.list and DEV in t:
                        d = await t[DEV]
                        if self.options.dump:
                            safe_dump(await rec_d(d), stream=self.stdout)
                        else:
                            print("device",
                                  d.path[len(DEV_DIR):-1],
                                  sep='\t',
                                  file=self.stdout)
                            for k, v in d.items():
                                if k in _SOURCES:
                                    for n, c in v.items():
                                        if hasattr(c, 'get'):
                                            c = c.get('value')

                                        print('%s/%s' % (k, n),
                                              c,
                                              sep='\t',
                                              file=self.stdout)
                                else:
                                    print(k, v, sep='\t', file=self.stdout)
                            print("")
                    else:
                        async for d in t.tagged(DEV):
                            print('/'.join(d.path[len(DEV_DIR):-1]),
                                  sep='\t',
                                  file=self.stdout)
                except KeyError:
                    print("'%s' does not exist" % (a, ), file=sys.stderr)
                    continue
        else:
            try:
                t = tree.lookup(args[0], name=DEV)
            except KeyError:
                raise CommandError("Device '%a' not found" % (args[0], ))
            else:
                if '/' in args[1]:
                    t = t.lookup(args[1])
                    if len(args) == 2:
                        for k, v in t.items():
                            print(k,
                                  v.get('value', '??'),
                                  sep='\t',
                                  file=self.stdout)
                    else:
                        for a in args[1:]:
                            try:
                                print(a, t[a], sep='\t', file=self.stdout)
                            except KeyError:
                                print("%s: not found" % (a, ), file=sys.stderr)
                elif len(args) == 2 and args[1] in _SOURCES:
                    t = t.lookup(args[1])
                    for k, v in t.items():
                        print(k, v, sep='\t', file=self.stdout)
                else:
                    for a in args[1:]:
                        try:
                            print(a, t[a], sep='\t', file=self.stdout)
                        except KeyError:
                            print("%s: not found" % (a, ), file=sys.stderr)
Exemple #29
0
    async def do(self, args):
        try:
            data = {}
            taskdefpath = ""
            name = ""
            p = 0

            taskpath = args[p].rstrip('/').lstrip('/')
            if taskpath == "":
                raise CommandError("Empty task path?")
            if taskpath[0] == ':' or '/:' in taskpath:
                raise CommandError("Don't add the tag")
            p += 1

            if not self._update:
                taskdefpath = args[p].rstrip('/').lstrip('/')
                if taskdefpath == "":
                    raise CommandError("Empty task definition path?")
                if taskdefpath[0] == ':' or '/:' in taskdefpath:
                    raise CommandError("Don't add the tag")
                p += 1
            while p < len(args):
                try:
                    k, v = args[p].split('=')
                except ValueError:
                    break
                p += 1
                if k == "name":
                    name = v
                else:
                    data[k] = v
            if not self._update:
                args[p]  # raises IndexError if nothing is left
            descr = " ".join(args[p:])
        except IndexError:
            raise CommandError("Missing command parameters")
        t = await self.setup(meta=False)
        if not self._update:
            try:
                td = await self.setup(meta=True)
                taskdef = await td.subdir(taskdefpath,
                                          name=TASKDEF,
                                          create=False)
            except KeyError:
                raise CommandError("Taskdef '%s' not found" % taskdefpath)

        try:
            task = await t.subdir(taskpath, name=TASK, create=not self._update)
        except KeyError:
            raise CommandError(
                "Task '%s' not found. (Use its path, not the name?)" %
                taskpath)
        if not self._update:
            await task.set('taskdef', taskdefpath, sync=False)
        p = self.options.parent
        if p is not None:
            if p == '-':
                with suppress(KeyError):
                    await task.delete('parent', sync=False)
            else:
                await task.set('parent', p, sync=False)

        if name:
            await task.set('name', name, sync=False)
        if descr:
            await task.set('descr', descr, sync=False)
        if data:
            d = await task.subdir('data', create=None)
            for k, v in data.items():
                if v == "":
                    try:
                        await d.delete(k, sync=False)
                    except KeyError:
                        pass
                else:
                    await d.set(k, v, sync=False, ext=True)
Exemple #30
0
	async def do(self,args):
		await self.root.setup(self)
		tree = self.root.tree
		seen = False
		if not args:
			t = await tree.lookup('bus','onewire')
			for srv,v in t.items():
				try:
					v = await v['bus']
				except (etcd.EtcdKeyNotFound,KeyError):
					pass
				else:
					for b in v.keys():
						seen = True
						print(srv,b.replace(' ','/'), sep='\t',file=self.stdout)
			if self.root.verbose and not seen:
				print("No buses known.", file=sys.stderr)
			return
		srv = args.pop(0)
		if not args:
			try:
				t = await tree.subdir('bus','onewire',srv,'bus', create=False,recursive=True)
			except (etcd.EtcdKeyNotFound,KeyError):
				pass
			else:
				for bus,dc in t.items():
					if dc.get('broken',0):
						print(bus,"*inaccessible*", sep='\t',file=self.stdout)
						seen = True
					dc = dc.get('devices',{})
					items = []
					for typ,v in dc.items():
						try:
							dt = device_types()[typ]
							tname = dt.name
						except KeyError:
							dt = OnewireDevice
							tname = '?'+typ
						items.append("%s:%d"%(tname,len(v)))
					print(bus.replace(' ','/'),*items, sep='\t',file=self.stdout)
					seen = True
			if self.root.verbose and not seen:
				print("No buses known.", file=sys.stderr)
			return
		bus = args.pop(0)
		if args:
			raise CommandError("Usage: conn onewire bus [server [bus]]")
		bus = bus.replace('/',' ')
		try:
			t = await tree.subdir('bus','onewire',srv, 'bus',bus,'devices', create=False,recursive=True)
		except (etcd.EtcdKeyNotFound,KeyError):
			raise CommandError("Bus %s:%s does not exist." % (srv,bus))
		for typ,v in t.items():
			try:
				dt = device_types()[typ]
				tname = dt.name
			except KeyError:
				dt = OnewireDevice
				tname = '?'+typ
			for dev in v.keys():
				print(typ+'.'+dev, tname)
				seen = True
		if self.root.verbose and not seen:
			print("No devices known.", file=sys.stderr)