On 13/10/11 21:50, Russell Bryant wrote:
(I'm going to use mhsh to refer to Matahari Shell for short.)
On 10/13/2011 12:01 PM, Zane Bitter wrote:
> This is a first attempt at coming up with some requirements for the
> proposed Matahari shell. It's mostly in the form of random things I've
> been thinking about, so at this stage everything is up for grabs. If
> anybody else has ideas floating around in their heads about what the
> shell should be, now would be a good time to get them out.
Thanks for getting this started.
> The shell needs to support the following:
> - Query for objects; filter by any combination of:
> + Broker (?) [How does this work with federated brokers?]
Can you give an example of what filtering on a broker would look like?
It makes sense to me that you need to provide a broker to connect to,
but I'm not sure how that applies to filtering with a query.
It looks like the client code allows you to connect to multiple brokers
at the same time, and normally queries will be sent to all of them. So
you can filter by querying only one broker, but it seems that if you
have an aggregating broker this does not allow you to effectively filter
by host in the general case. So this is probably not that useful; in
fact I expect the shell would allow only one broker connection at a time.
You can filter by agent as well. However, I think this whole section is
in some ways obviated by the discussion below.
> + Package
> + Class
> + Property value
> - Read properties/statistics of objects
> - Wait for events (?)
One case I could see myself using would be to specify an agent to
connect to and just watch for events that originate from that agent.
Perhaps it also makes sense to be able to see all events from all agents
on the bus.
There's a possibility of more complex use cases, as well. Consider the
services agent. You can run Resources::invoke() and have it check the
status of a service or resource agent on a regular basis, and it will
fire off events if the status changes. Maybe someone would want to see
all service state changes from an agent, or all service state change
events of all of the Services agents on the bus.
So, run mhsh to:
- get all events
- get all events from all agents that match a package:class
- get all events from a specific agent instance
- get all events from a specific agent of a specific event type
Sounds good. What would we do in practice when a matching event occurs?
Just print a message to the console?
> - Invoke methods
> - Perform introspection: list and get types of properties, statistics,
> methods, method parameters
>
>
> Configuration:
> - The shell should read the /etc/sysconfig/matahari file for
> configuration of the broker, port, SSL&c.
It's convenient, but not portable.
Up to this point, AFAIK, the stuff using /etc/sysconfig/matahari and
friends are the bits that are distribution specific anyway (init
scripts, systemd unit).
That's technically true, but wouldn't we have an equivalent of
/etc/sysconfig/matahari on any distro we're likely to package for? I'd
like to think the init scripts are _pretty_ portable, at least to other
Linux distros.
We can have it check for that, but we'll also need something that it
cross distro compatible, like /etc/matahari/mhsh.conf or whatever.
Speaking of portability, is running mhsh from Windows a requirement? I
don't think it is, since in general, Windows is treated as something we
need to be able to manage, not something we should manage from.
Agreed that it's not a requirement. Having said that, you'd almost have
to be trying to make it non-portable, and I suspect that in a good
design any platform-specific stuff would end up concentrated in a pretty
small region even without that as a requirement.
> - There should be CLI options to override those values. Where possible
> these should match those used by the Matahari agents/consoles.
>
> Consumers:
> The shell should be accessible both interactively to CLI users and to
> external scripts (e.g. bash scripts) that want to make use of it.
> Features such as tab completion are a low priority initially, but we
> will want them in the long term. Readline support (e.g. command history)
> and online help will probably be required from the outset.
>
> There are broadly two approaches to shell design that could be followed:
> - 1) Stateless:
> All of the data needed to execute a particular command must be entered
> as parameters.
> + Downside: it's a pain for an interactive user, especially when
> performing multiple actions on a single object.
>
> - 2) Stateful:
> Switch between various modes that retain data about the current state so
> that it does not need to be entered as parameters every time. e.g. the
> Cisco IOS command line.
> + Downside: it can mean that scripts using the shell also have to
> maintain state.
>
> qmf-tool uses a hybrid of these two approches that arguably incorporates
> the downsides of both ;)
>
> On balance I would recommend some kind of stateful model, but with an
> emphasis on making it easy for scripts to inspect the current state, or
> at least return to a known state.
>
Works for me.
>
> Parallelisation:
> The QMF Python libraries support asynchronous method calls. Therefore we
> can, in theory, implement the shell in such a way that methods can be
> invoked on an entire group of objects (selected by some query) at once.
> This seems to be one of the big selling points of things like
> MCollective, which goes out of its way to say that "we’re not simply a
> fancy SSH “for loop.” MCollective use modern tools like Publish
> Subscribe Middleware and modern philosophies like real time discovery of
> network resources using meta data and not hostnames. Delivering a very
> scalable and very fast parallel execution environment." Matahari is
> built on top of QMF for the same reasons; do we need to exploit that in
> the shell?
I'm not sure on this yet. I think it depends on what use cases we end
up with and if they justify the complexity. Obviously the
parallelization in QMF is important, but I don't know about in mhsh.
IMO if we can provide people with a way to efficiently manage a large
number of machines using mhsh and an expect script (or equivalent), I
think it would drive adoption much more than requiring them to write
asynchronous Python, Ruby or, worse, C++ code to do it.
>
>
> Other Considerations:
> - We already have qmf-tool. What do we need to do better/differently
> in a Matahari shell?
This is the point that I keep hitting when the idea of mhsh comes up.
Most of what we have discussed in this message so far could just be
enhancements to qmf-tool, or a new replacement qmf-tool like utility.
Agreed.
So, we may end up with ideas for 2 projects:
1) a fancy new-and-improved qmf-tool, for the Matahari/QMF power-user
2) mhsh, a simplified Matahari specific shell
I'm not sure we need or want to do both. I like idea #2.
For mhsh to make sense, it has to do something specific to Matahari
agents. What would that be? Maybe we can come up with something that's
a level of abstraction higher than qmf-tool. There are some conventions
followed by all Matahari agents (org.matahariproject package agents,
anyway) that we could take advantage of here.
Each of our agents expose a hostname and common UUID property. That
means that under the hood, we could discover all agents and associate
them together as a host.
host = collection of all agents with a given value of the uuid
property
(just prototyping ideas here ...)
mhsh> list hosts
hostname | UUID
-------------------------------------------------------------
hostA | adsfadsfasdfasdfasdfadsf
hostB | woeiruoweiurowieurowieur
I like this idea a lot. It makes much more sense for users to deal with
Matahari at this level of abstraction. One problem: this convention is
not forced on external agents. I don't think that's insurmountable though.
Something like that would be a bit more consumable than "list
agents" in
a more generic qmf-tool. From there, under each host would be the set
of agents on that host. Here we hit another interesting convention. We
know that for each agent, there is a single instance of the class it
provides and that its address is the same as the class name. So, the
shell user doesn't need to know about querying at all (at least QMF
object queries).
This part is definitely not enforced on external agents, and definitely
would be a big problem. libvirt-qmf for example manages many objects.
There is, however, a root-level object (org.libvirt.Node in this case).
Perhaps we could modify Matahari to require that a root-level object be
specified, and augment its schema automatically with a UUID property.
(Note: this assumes unique hostnames. Perhaps we could support using
the UUID, as well)
We would definitely want to use UUIDs internally, at least. It's
important to be able to identify hosts uniquely.
mhsh> list host hostA
Host
Sysconfig
Services
Network
Once you get down to the object level, it may look sort of similar to
qmf-tool. You could list properties/statistics and call methods.
mhsh> show hostA Host
... properties/statistics ...
mhsh> show hostA Host hostname
... value of single property, hostname ...
mhsh> call hostA Host get_uuid filesystem
... result of method call ...
Introspection is something that would be really nice in qmf-tool. In
mhsh, in the spirit of simplicity, that could be in the form of tab
completion.
mhsh> call<tab>
... tab complete hosts ...
mhsh> call hostA<tab>
... tab complete classes ...
mhsh> call hostA Host<tab>
... tab complete available methods ...
mhsh> call hostA Host get_uuid<tab>
... tab complete arguments (see named arguments note below) ...
mhsh> show hostA Host<tab>
... tab complete properties ...
We'd probably want a command for it as well, for the benefit of scripts,
but tab completion on everything would definitely be cool.
Incidentally, these examples are a classic demonstration of a stateless
shell; I think if we're prepared to move away from this model we can
quite easily support parallelised commands. In a stateful model, the
commands above session might look something like:
mhsh> select host <tab>
hostA hostB
mhsh> select host hostA
mhsh (host)> select package <tab>
org.matahariproject org.libvirt
mhsh (host)> select package org.matahariproject class <tab>
Host Network Service
Sysconfig
mhsh (host)> select class Host
mhsh (host/class)> call <tab>
get_uuid identify reboot
set_uuid shutdown
mhsh (host/class)> call get_uuid <tab>
lifetime= LIFETIME <cr>
mhsh (host/class)> call get_uuid lifetime=filesystem
org.matahariproject.Host@hostA Success
{ uuid: '5bde1acde645c48d644012ad60080df2' }
mhsh (host/class)> show <tab>
load hostname last_updated
free_swap sequence free_mem
os process_statistics
cpu_count cpu_model cpu_cores
wordsize swap custom_uuid
memory update_interval cpu_flags
arch uuid
This can easily be modified to allow e.g.
mhsh> select host hostA, hostB
To perform the action on multiple hosts in parallel.
I'm not sure what the performance of tab-complete would be like, though,
if it had to look at a large number of objects on a large number of
hosts to get the info. We can probably cheat here though.
One usability issue with qmf-tool that we could address (again, maybe
in
a new qmf-tool, but also in mhsh), is the handling of arguments to a
method call. qmf-tool on supports positional arguments, and it enforces
all arguments to be specified. In reality, not all arguments are
required. It would be nice to be able to (optionally?) used named
arguments, and in that case, not require all of them to be specified.
mhsh> call hostA Host get_uuid lifetime=filesystem
... result of method call ...
Good idea. That would definitely be a plus, and it should be pretty
trivial to add.
> - Ideally the CLI part should be a wrapper over a Python API,
so that
> authors of Python scripts can consume the API directly.
Agreed.