Hello,
here is the proposal for the Server Role API:
* Plugin architecture * Daemon must exit, when not in use (all D-Bus clients exited)
D-Bus server API:
org.fedoraproject.ServerRoleManager1 ------------------------------------
Properties
version:s # server role manager version state:s # active/inactive/dead? roles:ao # role objects list
Methods
getRole(role:o)→o # get role by object getNamedRole(name:s)→o # get role by name getActiveRoles()→ao # get active role object list
org.fedoraproject.ServerRoleManager1.roles.$n ---------------------------------------------
Properties (general) # role settings
name:s (ro) # role name version:s (ro) # role version state:s (ro) # deployed/started/inactive/dead? activate_time:i (ro) # time of activation deploy_time:i (ro) # time of deployment is_configured:b (ro) # is this role configured? packages:as (ro) # packages and @groups services:a{sas} (ro) # services to be enabled and/or started: "enable": [s] and "start": [s] firewall:a{sas} (ro) # firewall dict ports: [s] and service: [s] #backup_paths:as # backup files and directories (directory trailing slash it means "everything below here") # ... # custom settings, passwords as key value pairs
Methods
deploy() # deploy role (i.e. running initial setup post-package-install, ipa-server-install) decommission() # decommision (example: moved to another machine, ipa-server-install -u ), stop if started
start() # start the role (startServices, installFirewall), fails if not deployed stop() # stop the role (stopServices, uninstallFirewall), fails if not started
updateRole() # update role: yum update; restartServices; updateFirewall reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
installPackages() # install packages and groups #uninstallPackages() # uninstall packages and groups, fails if deployed - not initially
startServices() # start the services restartServices() # restart the services stopServices() # stop the services
installFirewall() # install firewall ports/services updateFirewall() # update firewall ports/services uninstallFirewall() # uninstall firewall ports/services
Thomas Woerner twoerner@redhat.com writes:
Some question that I had on first reading. Hopefully they can help to improve the API, although most of them are obvious and you probably have thought of them already.
org.fedoraproject.ServerRoleManager1
Properties
version:s # server role manager version state:s # active/inactive/dead? roles:ao # role objects list
Methods
getRole(role:o)→o # get role by object
What is the input object? On first glance, this looks like the identity function, no? :)
getNamedRole(name:s)→o # get role by name getActiveRoles()→ao # get active role object list
What is "active", exactly? Is it the same as state == "started"?
org.fedoraproject.ServerRoleManager1.roles.$n
What is the $n here? Is it the version of the interface? (If we specify a concrete API, we just need one name. Role specific APIs should be separate interfaces on the same object.)
Properties (general) # role settings
name:s (ro) # role name version:s (ro) # role version state:s (ro) # deployed/started/inactive/dead?
What is the state before the role is deployed?
Changing state is not instantanous. Can I see when a role is currently being deployed (and how long that is still estimated to take)?
I guess a role can also be in a "failed" state, where it is supposed to be active/started but something has gone wrong.
activate_time:i (ro) # time of activation deploy_time:i (ro) # time of deployment is_configured:b (ro) # is this role configured?
What does "configured" mean? It's not the same as "active" or "started", right? Can I start a unconfigured role? Could this be a state?
packages:as (ro) # packages and @groups services:a{sas} (ro) # services to be enabled and/or started: "enable": [s] and "start": [s] firewall:a{sas} (ro) # firewall dict ports: [s] and service: [s] #backup_paths:as # backup files and directories (directory trailing slash it means "everything below here") # ... # custom settings, passwords as key value pairs
It might not a good idea to put sensitive data like passwords into properties. The common practise seems to be to have a separate method to return the secrets. This is probably done to make implementing access control easier, but I am not sure.
Methods
deploy() # deploy role (i.e. running initial setup post-package-install, ipa-server-install)
How can I cancel?
decommission() # decommision (example: moved to another machine, ipa-server-install -u ), stop if started
start() # start the role (startServices, installFirewall), fails if not deployed stop() # stop the role (stopServices, uninstallFirewall), fails if not started
updateRole() # update role: yum update; restartServices; updateFirewall
How can I see whether an update for the role is available?
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
A role could specific which program to run to do a interactive configuration. For terminal, for a graphical session, and for Cockpit (by specifying a module that Cockpit will load).
installPackages() # install packages and groups #uninstallPackages() # uninstall packages and groups, fails if deployed - not initially
startServices() # start the services restartServices() # restart the services stopServices() # stop the services
installFirewall() # install firewall ports/services updateFirewall() # update firewall ports/services uninstallFirewall() # uninstall firewall ports/services
Is there anything more to these than convenience? E.g., can I just take the 'packages' properties and use it with the package management API of my choice? If we already have a good UI for the package management API, with highly polished progress reporting and error handling, say, it is probably better to just use it instead of trying to polish this API to the same level.
Thanks!
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 06/02/2014 02:51 AM, Marius Vollmer wrote:
Thomas Woerner twoerner@redhat.com writes:
Some question that I had on first reading. Hopefully they can help to improve the API, although most of them are obvious and you probably have thought of them already.
org.fedoraproject.ServerRoleManager1
Properties
version:s # server role manager version state:s # active/inactive/dead? roles:ao # role objects list
Methods
getRole(role:o)→o # get role by object
What is the input object? On first glance, this looks like the identity function, no? :)
I missed this one, but I'm puzzled too. Thomas?
getNamedRole(name:s)→o # get role by name getActiveRoles()→ao # get active role object list
What is "active", exactly? Is it the same as state == "started"?
IIRC, we're defining "active" as "we've deployed the role on this system". That could mean "deployed but not currently started". It might also mean "We've installed the role but have not yet configured it".
org.fedoraproject.ServerRoleManager1.roles.$n
What is the $n here? Is it the version of the interface? (If we specify a concrete API, we just need one name. Role specific APIs should be separate interfaces on the same object.)
I think it's supposed to be the role name, but Thomas can correct me.
So: org.fedoraproject.ServerRoleManager1.roles.DomainController or org.fedoraproject.ServerRoleManager1.roles.DatabaseServer
Properties (general) # role settings
name:s (ro) # role name version:s (ro) # role version state:s (ro) # deployed/started/inactive/dead?
What is the state before the role is deployed?
Good point, we probably need "unconfigured".
Changing state is not instantanous. Can I see when a role is currently being deployed (and how long that is still estimated to take)?
Estimating the deployment time is out of scope (we probably won't realistically know the answer).
Having "deploying" and "starting" states would be a good idea, though.
I guess a role can also be in a "failed" state, where it is supposed to be active/started but something has gone wrong.
I think that's what "dead" means, but maybe that should be more clear.
I'm not really sure what "inactive" means. I suspect we should converge deployed and inactive in some way.
activate_time:i (ro) # time of activation deploy_time:i (ro) # time of deployment is_configured:b (ro) # is this role configured?
What does "configured" mean? It's not the same as "active" or "started", right? Can I start a unconfigured role? Could this be a state?
A "configured" Role can be in any of "deployed", "starting", "started" or "dead" states.
packages:as (ro) # packages and @groups services:a{sas} (ro) # services to be enabled and/or started: "enable": [s] and "start": [s] firewall:a{sas} (ro) # firewall dict ports: [s] and service: [s] #backup_paths:as # backup files and directories (directory trailing slash it means "everything below here") # ... # custom settings, passwords as key value pairs
It might not a good idea to put sensitive data like passwords into properties. The common practise seems to be to have a separate method to return the secrets. This is probably done to make implementing access control easier, but I am not sure.
Worth considering, but as this API is essentially "root-only", I'm not sure it's urgent.
Methods
deploy() # deploy role (i.e. running initial setup post-package-install, ipa-server-install)
How can I cancel?
Cancellation isn't currently supported (in part because we don't presently have a guarantee that installing Roles can reasonably be rolled back).
I don't want to have a cancellation routine without a guaranteed clean-up. This is something we may be able to address with managing Roles in containers, though.
Thomas, maybe we can add a cancelDeployment() routine, but ensure that clients are aware that DeploymentUncancellable or something is an expected possibility.
decommission() # decommision (example: moved to another machine, ipa-server-install -u ), stop if started
start() # start the role (startServices, installFirewall), fails if not deployed stop() # stop the role (stopServices, uninstallFirewall), fails if not started
updateRole() # update role: yum update; restartServices; updateFirewall
How can I see whether an update for the role is available?
Good question. Add a checkForUpdates() method?
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
A role could specific which program to run to do a interactive configuration. For terminal, for a graphical session, and for Cockpit (by specifying a module that Cockpit will load).
Out of scope. We don't want the API to be interactive to that level. It introduces too much complexity.
The API will be pretty much static, so the UIs should be able to just do whatever interaction they want and then push down the final results.
installPackages() # install packages and groups #uninstallPackages() # uninstall packages and groups, fails if deployed - not initially
startServices() # start the services restartServices() # restart the services stopServices() # stop the services
installFirewall() # install firewall ports/services updateFirewall() # update firewall ports/services uninstallFirewall() # uninstall firewall ports/services
Is there anything more to these than convenience? E.g., can I just take the 'packages' properties and use it with the package management API of my choice? If we already have a good UI for the package management API, with highly polished progress reporting and error handling, say, it is probably better to just use it instead of trying to polish this API to the same level.
Right, these are convenience. In the case of Cockpit, I'd expect you to use your own package-installation tool.
We should probably add 'getPackageList()' as a method that Cockpit can use, so it doesn't have to maintain a duplicate list, though.
Stephen Gallagher sgallagh@redhat.com writes:
On 06/02/2014 02:51 AM, Marius Vollmer wrote:
What is "active", exactly? Is it the same as state == "started"?
IIRC, we're defining "active" as "we've deployed the role on this system". That could mean "deployed but not currently started". It might also mean "We've installed the role but have not yet configured it".
Would it be possible to explain "active" in terms of the operations on roles? For example, a role becomes "active" after a successful "deploy", and "decommission" causes a role to no longer be "active".
org.fedoraproject.ServerRoleManager1.roles.$n
What is the $n here? Is it the version of the interface? (If we specify a concrete API, we just need one name. Role specific APIs should be separate interfaces on the same object.)
I think it's supposed to be the role name, but Thomas can correct me.
So: org.fedoraproject.ServerRoleManager1.roles.DomainController or org.fedoraproject.ServerRoleManager1.roles.DatabaseServer
But we don't define those interfaces here, no? We only define the generic one that every role should support, and we just need one concrete name for it. org.fedoraproject.ServerRoleManager1.Role?
What is the state before the role is deployed?
Good point, we probably need "unconfigured".
So "deploy" goes from "unconfigured" to "deployed"? Did you mean "undeployed"?
Sorry for being pedantic, but IMO defining the states is not trivial, and a major part of the API. So let's not hand wave them away now and treat them as a random string that we can easily change later. :-)
Changing state is not instantanous. Can I see when a role is currently being deployed (and how long that is still estimated to take)?
Estimating the deployment time is out of scope (we probably won't realistically know the answer).
Having "deploying" and "starting" states would be a good idea, though.
A common approach would be to export "Job" objects on D-Bus that carry progress information and have a Cancel method. "deploy" would return the path of such an object.
What does "configured" mean? It's not the same as "active" or "started", right? Can I start a unconfigured role? Could this be a state?
A "configured" Role can be in any of "deployed", "starting", "started" or "dead" states.
In what states can a "unconfigured" role be? Maybe "unconfigured" can be a state.
How can I cancel?
Cancellation isn't currently supported (in part because we don't presently have a guarantee that installing Roles can reasonably be rolled back).
Hmm, users will always find a way to cancel even without an explicit button, so roles need to be prepared for that anyway, I'd say.
I don't want to have a cancellation routine without a guaranteed clean-up. This is something we may be able to address with managing Roles in containers, though.
I think interrupting yum is well defined, no?
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
A role could specific which program to run to do a interactive configuration. For terminal, for a graphical session, and for Cockpit (by specifying a module that Cockpit will load).
Out of scope. We don't want the API to be interactive to that level. It introduces too much complexity.
The API will be pretty much static, so the UIs should be able to just do whatever interaction they want and then push down the final results.
Sure, I was actually going in the other direction, but I wasn't clear: _Instead_ of reconfigureRole (which can't be used generically), the generic role description would just say what program to run for a limited number of session types. FreeIPA would say "ipa-server-install" here, and Cockpit would offer to run that in a terminal.
The state of the role would tell when it is legal to run that program.
Any configuration APIs should be on the role specific interfaces such as org.fedoraproject.ServerRoleManager1.Role.DomainController, no?
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 06/03/2014 03:19 AM, Marius Vollmer wrote:
Stephen Gallagher sgallagh@redhat.com writes:
On 06/02/2014 02:51 AM, Marius Vollmer wrote:
What is "active", exactly? Is it the same as state == "started"?
IIRC, we're defining "active" as "we've deployed the role on this system". That could mean "deployed but not currently started". It might also mean "We've installed the role but have not yet configured it".
Would it be possible to explain "active" in terms of the operations on roles? For example, a role becomes "active" after a successful "deploy", and "decommission" causes a role to no longer be "active".
org.fedoraproject.ServerRoleManager1.roles.$n
What is the $n here? Is it the version of the interface? (If we specify a concrete API, we just need one name. Role specific APIs should be separate interfaces on the same object.)
I think it's supposed to be the role name, but Thomas can correct me.
So: org.fedoraproject.ServerRoleManager1.roles.DomainController or org.fedoraproject.ServerRoleManager1.roles.DatabaseServer
But we don't define those interfaces here, no? We only define the generic one that every role should support, and we just need one concrete name for it. org.fedoraproject.ServerRoleManager1.Role?
What is the state before the role is deployed?
Good point, we probably need "unconfigured".
So "deploy" goes from "unconfigured" to "deployed"? Did you mean "undeployed"?
Sorry for being pedantic, but IMO defining the states is not trivial, and a major part of the API. So let's not hand wave them away now and treat them as a random string that we can easily change later. :-)
No, you are absolutely correct that we need to have these sorted out or it will cause problems later. I'm going to defer for the moment to Thomas Woerner for his opinion on the above comments.
Changing state is not instantanous. Can I see when a role is currently being deployed (and how long that is still estimated to take)?
Estimating the deployment time is out of scope (we probably won't realistically know the answer).
Having "deploying" and "starting" states would be a good idea, though.
A common approach would be to export "Job" objects on D-Bus that carry progress information and have a Cancel method. "deploy" would return the path of such an object.
Yes, this is absolutely the approach we would want to take, but we still want the '*ing' states in case some *other* process communicating with the API shows up (such as Cockpit monitoring things while an admin is using the CLI)
What does "configured" mean? It's not the same as "active" or "started", right? Can I start a unconfigured role? Could this be a state?
A "configured" Role can be in any of "deployed", "starting", "started" or "dead" states.
In what states can a "unconfigured" role be? Maybe "unconfigured" can be a state.
Good question; we need to figure out how this fits with active/inactive. I think perhaps we need to step back and try to re-think the states from the beginning. I get the impression that trying to iteratively revise the ones we came up with first is not proving effective.
How can I cancel?
Cancellation isn't currently supported (in part because we don't presently have a guarantee that installing Roles can reasonably be rolled back).
Hmm, users will always find a way to cancel even without an explicit button, so roles need to be prepared for that anyway, I'd say.
Well, the reason I make that statement is that cancellation isn't often supported by the *underlying* mechanisms. For example, if you abort ipa-server-install, there's no telling what state your system will be in and not guarantee that you can run 'ipa-server-install -u' and get your system back to how it was before.
I don't want to have a cancellation routine without a guaranteed clean-up. This is something we may be able to address with managing Roles in containers, though.
I think interrupting yum is well defined, no?
Yeah, it's one of the most potentially catastrophic operations you can do :-(
This is part of why I'm advocating the use of docker images for any roles that can support them. At least that way, we can simply destroy the container and know that the host system is untouched. However, that won't work for all Roles (FreeIPA being the obvious one, right now).
So I'm okay with having a cancellation routine, but clients will have to be able to expect and handle a "CannotCancel" D-BUS error if the specific Role cannot be canceled.
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
A role could specific which program to run to do a interactive configuration. For terminal, for a graphical session, and for Cockpit (by specifying a module that Cockpit will load).
Out of scope. We don't want the API to be interactive to that level. It introduces too much complexity.
The API will be pretty much static, so the UIs should be able to just do whatever interaction they want and then push down the final results.
Sure, I was actually going in the other direction, but I wasn't clear: _Instead_ of reconfigureRole (which can't be used generically), the generic role description would just say what program to run for a limited number of session types. FreeIPA would say "ipa-server-install" here, and Cockpit would offer to run that in a terminal.
I'd prefer not doing that in v1, honestly. The goal here is for the API to always produce a known-good state following best-practices. Giving them an official way to bypass those choices defeats the purpose somewhat.
The state of the role would tell when it is legal to run that program.
Any configuration APIs should be on the role specific interfaces such as org.fedoraproject.ServerRoleManager1.Role.DomainController, no?
Yes, was that unclear?
2014-06-03 9:19 GMT+02:00 Marius Vollmer marius.vollmer@redhat.com:
Stephen Gallagher sgallagh@redhat.com writes:
On 06/02/2014 02:51 AM, Marius Vollmer wrote:
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
A role could specific which program to run to do a interactive configuration. For terminal, for a graphical session, and for Cockpit (by specifying a module that Cockpit will load).
Out of scope. We don't want the API to be interactive to that level. It introduces too much complexity.
The API will be pretty much static, so the UIs should be able to just do whatever interaction they want and then push down the final results.
Sure, I was actually going in the other direction, but I wasn't clear: _Instead_ of reconfigureRole (which can't be used generically), the generic role description would just say what program to run for a limited number of session types. FreeIPA would say "ipa-server-install" here, and Cockpit would offer to run that in a terminal.
Nonononono. You might just as well define that IPA.defineRole is equivalent to (ipa-server-install $the_value_of_param_a $the_value_of_param_b), and so on for every operation, ship an XML file with these definitions (and perhaps one more file for X/Wayland UIs if anything provided them), and drop the D-Bus API completely, then.
I think we do want the API to be used generically, by tools that *can* be generic. E.g. store the role configs in a configuration management system as files, and have exactly the same D-Bus call (or command-line utility) to deploy them, perhaps in the shell-script world something like
for f in /etc/our-site-role-configs/*; do server-role deploy
--kickstart-like $f; done
Good UI can’t be generic and I basically don’t think we can avoid writing a Cockpit-and-roles-specific UI if we want any non-CLI UI at all. (i.e., cockpit-specific but not-roles-specific wouldn‘t work at all, and roles-specific but not-cockpit-specific mostly wouldn’t work either).
Overall, I think Stephen’s proposal to let the operations accept a fully-prepared configuration (like the a{sv} above), is a reasonable approach at the API level. Mirek
Miloslav Trmač mitr@volny.cz writes:
Good UI can’t be generic and I basically don’t think we can avoid writing a Cockpit-and-roles-specific UI if we want any non-CLI UI at all. (i.e., cockpit-specific but not-roles-specific wouldn‘t work at all, and roles-specific but not-cockpit-specific mostly wouldn’t work either).
Yes, I agree. However, that cockpit-specific-and-role-specific UI can be delivered as part of the role and hooked into Cockpit in a generic way. (Not just yet, but soon.)
2014-06-02 18:46 GMT+02:00 Stephen Gallagher sgallagh@redhat.com:
On 06/02/2014 02:51 AM, Marius Vollmer wrote:
Thomas Woerner twoerner@redhat.com writes:
Thomas, maybe we can add a cancelDeployment() routine, but ensure that clients are aware that DeploymentUncancellable or something is an expected possibility.
Note that this has larger implications, notably the D-Bus server must not block while performing a deploy() operation to be able to act on the cancelDeployment() call.
Is there anything more to these than convenience? E.g., can I just
take the 'packages' properties and use it with the package management API of my choice? If we already have a good UI for the package management API, with highly polished progress reporting and error handling, say, it is probably better to just use it instead of trying to polish this API to the same level.
Right, these are convenience. In the case of Cockpit, I'd expect you to use your own package-installation tool.
If the very first user of the high-level API decided to instead bypass it and perform low-level operations, that’d be a *very bad* sign. Could we instead learn from the cockpit API and add similar level of polish here? Mirek
Miloslav Trmač mitr@volny.cz writes:
2014-06-02 18:46 GMT+02:00 Stephen Gallagher sgallagh@redhat.com:
On 06/02/2014 02:51 AM, Marius Vollmer wrote:
Thomas Woerner twoerner@redhat.com writes:
Thomas, maybe we can add a cancelDeployment() routine, but ensure that clients are aware that DeploymentUncancellable or something is an expected possibility.
Note that this has larger implications, notably the D-Bus server must not block while performing a deploy() operation to be able to act on the cancelDeployment() call.
Hmm, the server can not block in any case. It must always be able to respond to things like GetActiveRoles etc.
Is there anything more to these than convenience? E.g., can I just
take the 'packages' properties and use it with the package management API of my choice? If we already have a good UI for the package management API, with highly polished progress reporting and error handling, say, it is probably better to just use it instead of trying to polish this API to the same level.
Right, these are convenience. In the case of Cockpit, I'd expect you to use your own package-installation tool.
If the very first user of the high-level API decided to instead bypass it and perform low-level operations, that’d be a *very bad* sign. Could we instead learn from the cockpit API and add similar level of polish here?
Well, I was mostly asking to understand the API better. We don't have any package or firewall management in Cockpit at this point at all. We would very likely just call "deploy" and "start".
On 06/02/2014 08:51 AM, Marius Vollmer wrote:
Thomas Woerner twoerner@redhat.com writes:
Some question that I had on first reading. Hopefully they can help to improve the API, although most of them are obvious and you probably have thought of them already.
org.fedoraproject.ServerRoleManager1
Properties
version:s # server role manager version state:s # active/inactive/dead? roles:ao # role objects list
Methods
getRole(role:o)→o # get role by object
What is the input object? On first glance, this looks like the identity function, no? :)
This one is not needed. I am removing it.
getNamedRole(name:s)→o # get role by name getActiveRoles()→ao # get active role object list
What is "active", exactly? Is it the same as state == "started"?
Yes, active was meant for started state.
We might extend this to getRoleByState(state:s)→ao. What do you think?
org.fedoraproject.ServerRoleManager1.roles.$n
What is the $n here? Is it the version of the interface? (If we specify a concrete API, we just need one name. Role specific APIs should be separate interfaces on the same object.)
$n is a number, because D-Bus only supports a limited character set here.
Properties (general) # role settings
name:s (ro) # role name version:s (ro) # role version state:s (ro) # deployed/started/inactive/dead?
What is the state before the role is deployed?
Changing state is not instantanous. Can I see when a role is currently being deployed (and how long that is still estimated to take)?
I guess a role can also be in a "failed" state, where it is supposed to be active/started but something has gone wrong.
The full set of states need to be defined still.
activate_time:i (ro) # time of activation deploy_time:i (ro) # time of deployment is_configured:b (ro) # is this role configured?
What does "configured" mean? It's not the same as "active" or "started", right? Can I start a unconfigured role? Could this be a state?
The user has added configuration options. This was mentioned after the proposal from Stephen.
Please define all properties, that might be useful.
packages:as (ro) # packages and @groups services:a{sas} (ro) # services to be enabled and/or started:
"enable": [s] and "start": [s] firewall:a{sas} (ro) # firewall dict ports: [s] and service: [s] #backup_paths:as # backup files and directories (directory trailing slash it means "everything below here") # ... # custom settings, passwords as key value pairs
It might not a good idea to put sensitive data like passwords into properties. The common practise seems to be to have a separate method to return the secrets. This is probably done to make implementing access control easier, but I am not sure.
Stephen, do you have a solution for this?
Methods
deploy() # deploy role (i.e. running initial setup
post-package-install, ipa-server-install)
How can I cancel?
Cancel while deploying? It was not planned for this now. Otherwise see decommission.
decommission() # decommision (example: moved to another
machine, ipa-server-install -u ), stop if started
start() # start the role (startServices,
installFirewall), fails if not deployed stop() # stop the role (stopServices, uninstallFirewall), fails if not started
updateRole() # update role: yum update; restartServices;
updateFirewall
How can I see whether an update for the role is available?
The updateFirewall call will for example be used if there is an role update. There is no mechanism to detect updates for now. Please define it.
reconfigureRole(a{sv}) # reconfgure role with new config settings
as key value pairs
A role could specific which program to run to do a interactive configuration. For terminal, for a graphical session, and for Cockpit (by specifying a module that Cockpit will load).
As far as I know interactive configuration is not a goal for now.
installPackages() # install packages and groups #uninstallPackages() # uninstall packages and groups, fails if
deployed - not initially
startServices() # start the services restartServices() # restart the services stopServices() # stop the services installFirewall() # install firewall ports/services updateFirewall() # update firewall ports/services uninstallFirewall() # uninstall firewall ports/services
Is there anything more to these than convenience? E.g., can I just take the 'packages' properties and use it with the package management API of my choice? If we already have a good UI for the package management API, with highly polished progress reporting and error handling, say, it is probably better to just use it instead of trying to polish this API to the same level.
I do not know. Stephen?
Thanks! _______________________________________________ server mailing list server@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/server
Thomas
Thomas Woerner twoerner@redhat.com writes:
There is no mechanism to detect updates for now. Please define it.
What about a property plus method for polling: UpdateAvailable and CheckForUpdates.
CheckForUpdates would initiate the poll if one isn't running right now, and then wait for the current poll to finish. It should interact nicely with the repo polling done by other components of the system that don't go via ServerRoleManager.
Hello, First of all, this is more comprehensive that I imagined the first version to be. So me having many questions is just because we haven’t been (at least that I’ve seen) been exploring all of these areas.
2014-05-30 17:35 GMT+02:00 Thomas Woerner twoerner@redhat.com:
org.fedoraproject.ServerRoleManager1
version:s # server role manager version
This is a string, how does the application compare them?
state:s # active/inactive/dead?
How could the D-Bus service return anything but “active”?
getActiveRoles()→ao # get active role object list
Why does this only allowing to list “active” roles? How does one list installed but not set up roles, and known but not installed roles? Or is the idea that nobody would need these lists because any UI allowing to install a role would know that role by name?
(getAllKnownRoles() + iterating over all roles would AFAICS be the most general API, but we can always add more functions and having getActiveRoles available doesn’t hurt at all, so perhaps we can just defer this.)
org.fedoraproject.ServerRoleManager1.roles.$n
name:s (ro) # role name version:s (ro) # role version
This is a string, how does the application compare them?
Version *of what*? Of a role-specific API, of the implementation of the role, of the underlying upstream project, of the persistent data format?
state:s (ro) # deployed/started/inactive/dead?
Why is there “inactive“ but not “active”? I guess this would all be helped with a state diagram.
activate_time:i (ro) # time of activation
Why is this necessary?
deploy_time:i (ro) # time of deployment
Why is this necessary?
is_configured:b (ro) # is this role configured?
Again, missing the state diagram.
packages:as (ro) # packages and @groups
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
services:a{sas} (ro) # services to be enabled and/or started:
"enable": [s] and "start": [s]
It seems to me that the caller managing the server doesn‘t need to know that; this is an implementation detail of the role, but I could be persuaded that cockpit needs this for actionable status display.
firewall:a{sas} (ro) # firewall dict ports: [s] and service: [s]
How is a port described with a single unstructured string? (And like services, perhaps the caller doesn’t need to know?)
#backup_paths:as # backup files and directories (directory
trailing slash it means "everything below here")
The trailing slash semantics seems superfluous; if the path named a directory without adding a slash, what would the backup program be expected to do?
deploy() # deploy role (i.e. running initial setup post-package-install, ipa-server-install)
How is interactivity, non-interactive kickstart-like deployment, error handling done?
decommission() # decommision (example: moved to another
machine, ipa-server-install -u ), stop if started
What does this do to configuration and data?
start() # start the role (startServices,
installFirewall), fails if not deployed stop() # stop the role (stopServices, uninstallFirewall), fails if not started
Does this have persistent effect (survive reboot)?
updateRole() # update role: yum update; restartServices;
updateFirewall
If the update requires more information from the user (even if just to confirm a non-reversible data migration), how is interactivity and non-interactive kickstart-like deployment done?
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
How do I get the full set of current settings to submit to this call?
installPackages() # install packages and groups
#uninstallPackages() # uninstall packages and groups, fails if deployed - not initially
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
startServices() # start the services
restartServices() # restart the services stopServices() # stop the services
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
installFirewall() # install firewall ports/services
updateFirewall() # update firewall ports/services uninstallFirewall() # uninstall firewall ports/services
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role. (And what does “update” do and when would I use it?) Mirek
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 06/03/2014 07:39 AM, Miloslav Trmač wrote:
Hello, First of all, this is more comprehensive that I imagined the first version to be. So me having many questions is just because we haven’t been (at least that I’ve seen) been exploring all of these areas.
2014-05-30 17:35 GMT+02:00 Thomas Woerner <twoerner@redhat.com mailto:twoerner@redhat.com>:
org.fedoraproject.ServerRoleManager1 ------------------------------__------
version:s # server role manager version
This is a string, how does the application compare them?
Good point; we probably only need this to be an integer.
state:s # active/inactive/dead?
How could the D-Bus service return anything but “active”?
Hmm, good question. That may indeed be superfluous.
getActiveRoles()→ao # get active role object list
Why does this only allowing to list “active” roles? How does one list installed but not set up roles, and known but not installed roles? Or is the idea that nobody would need these lists because any UI allowing to install a role would know that role by name?
"active" includes installed-but-not-configured roles.
(getAllKnownRoles() + iterating over all roles would AFAICS be the most general API, but we can always add more functions and having getActiveRoles available doesn’t hurt at all, so perhaps we can just defer this.)
Yeah, we probably need getAvailableRoles()
org.fedoraproject.ServerRoleManager1.roles.$n ------------------------------__--------------- name:s (ro) # role name version:s (ro) # role version
This is a string, how does the application compare them?
See above.
Version /of what/? Of a role-specific API, of the implementation of the role, of the underlying upstream project, of the persistent data format?
The implementation of the role, which includes the role-specific API and persistent data format. The underlying upstream project(s) should explicitly NOT be referenced here. (And in fact, they could even change in the future).
state:s (ro) # deployed/started/inactive/__dead?
Why is there “inactive“ but not “active”? I guess this would all be helped with a state diagram.
See the other branch of this thread for discussion of states.
activate_time:i (ro) # time of activation
Why is this necessary?
Informative, not necessary.
deploy_time:i (ro) # time of deployment
Why is this necessary?
Informative, not necessary.
is_configured:b (ro) # is this role configured?
Again, missing the state diagram.
packages:as (ro) # packages and @groups
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
This is something we want clients to be able to get, in case they want to manage packages themselves (e.g. Cockpit).
services:a{sas} (ro) # services to be enabled and/or started: "enable": [s] and "start": [s]
It seems to me that the caller managing the server doesn‘t need to know that; this is an implementation detail of the role, but I could be persuaded that cockpit needs this for actionable status display.
Yes, Cockpit will need this for display purposes.
firewall:a{sas} (ro) # firewall dict ports: [s] and service: [s]
How is a port described with a single unstructured string? (And like services, perhaps the caller doesn’t need to know?)
"53/udp" and similarly useful for Cockpit display/monitoring.
#backup_paths:as # backup files and directories (directory trailing slash it means "everything below here")
The trailing slash semantics seems superfluous; if the path named a directory without adding a slash, what would the backup program be expected to do?
Yeah, good point. We can base it on type rather than trailing slash. (I thought about that after we had the discussion as well, but didn't follow up).
deploy() # deploy role (i.e. running initial setup post-package-install, ipa-server-install)
How is interactivity, non-interactive kickstart-like deployment, error handling done?
No interactivity. You give it all the necessary data, then watch the Job for completion.
decommission() # decommision (example: moved to another machine, ipa-server-install -u ), stop if started
What does this do to configuration and data?
<handwave>Role-specific</handwave>
I'd suggest that we might want to copy any data referenced by 'backup_paths' (when implemented) to a recovery directory, just in case.
start() # start the role (startServices, installFirewall), fails if not deployed stop() # stop the role (stopServices, uninstallFirewall), fails if not started
Does this have persistent effect (survive reboot)?
I'd say make that an input value, default to persistent.
updateRole() # update role: yum update; restartServices; updateFirewall
If the update requires more information from the user (even if just to confirm a non-reversible data migration), how is interactivity and non-interactive kickstart-like deployment done?
Given the nature of open-source projects, the only safe assumption is that *every* updateRole includes a non-reversible data migration. Thus the client tools should just always warn of this. I realize this isn't a good answer.
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
How do I get the full set of current settings to submit to this call?
They are exposed as the * properties of the role object.
installPackages() # install packages and groups #uninstallPackages() # uninstall packages and groups, fails if deployed - not initially
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
Doesn't need to know what?
startServices() # start the services restartServices() # restart the services stopServices() # stop the services
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
Same question.
installFirewall() # install firewall ports/services updateFirewall() # update firewall ports/services uninstallFirewall() # uninstall firewall ports/services
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role. (And what does “update” do and when would I use it?)
Thomas?
2014-06-03 13:55 GMT+02:00 Stephen Gallagher sgallagh@redhat.com:
On 06/03/2014 07:39 AM, Miloslav Trmač wrote:
2014-05-30 17:35 GMT+02:00 Thomas Woerner <twoerner@redhat.com mailto:twoerner@redhat.com>: org.fedoraproject.ServerRoleManager1.roles.$n ------------------------------__---------------
version:s (ro) # role version
Version /of what/? Of a role-specific API, of the implementation of the role, of the underlying upstream project, of the persistent data format?
The implementation of the role, which includes the role-specific API and persistent data format.
How would the caller map from role version 5 to role API 3 and persistent data format 2? (“We’re not doing that for the first version” is quite acceptable, I just want to be clear about the semantics.)
deploy() # deploy role (i.e. running initial setup post-package-install, ipa-server-install)
How is interactivity, non-interactive kickstart-like deployment, error handling done?
No interactivity. You give it all the necessary data, then watch the Job for completion.
OK; then how did I give it the data, and how do I watch the job?
start() # start the role (startServices, installFirewall), fails if not deployed stop() # stop the role (stopServices, uninstallFirewall), fails if not started
Does this have persistent effect (survive reboot)?
I'd say make that an input value, default to persistent.
I should have said this right away: It seems to me we actually only need the persistent version. Non-persistence is just not that useful, especially considering the corner cases like sudden power loss reverting your configuration.
updateRole() # update role: yum update;
restartServices; updateFirewall
If the update requires more information from the user (even if just to confirm a non-reversible data migration), how is interactivity and non-interactive kickstart-like deployment done?
Given the nature of open-source projects, the only safe assumption is that *every* updateRole includes a non-reversible data migration.
I don’t think it’s that bad even in Fedora (though it *would* make our earlier discussions about more coordinated upstream server/role updates more critical), and for RHEL and the like it’s going to be very much the rare case. (At least assuming that updateRole() would be called for ~every package update, not only when upgrading to a new major version.)
reconfigureRole(a{sv}) # reconfgure role with new config settings as key value pairs
How do I get the full set of current settings to submit to this call?
They are exposed as the * properties of the role object.
Can I enumerate them? (In a way that doesn't include things like “activate_time”.) IMHO this *should* be possible to do generically (fedora-server save-state ipa > foo.xml) without knowledge of the particular role.
installPackages() # install packages and groups
#uninstallPackages() # uninstall packages and groups, fails if deployed - not initially
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
Doesn't need to know what?
Anything about packages; the caller should just say “install postgres” and never hear about RPMs. (Notably, this would allow us to *transparently* switch from RPMs to Docker images—and even back the other way if necessary.)
startServices() # start the services restartServices()
# restart the services stopServices() # stop the services
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
Same question.
Same answer: just say “start postgres” and never hear about systemd units. Especially when there *already* is start() and stop(), exposing the subcomponents of that API is rather redundant.
(Separately: In the internal implementation, should the API talk about all systemd unit types, or only services, BTW? I’m thinking about socket units in particular.) Mirek
2014-06-03 14:11 GMT+02:00 Miloslav Trmač mitr@volny.cz:
installPackages() # install packages and groups
#uninstallPackages() # uninstall packages and groups, fails if deployed - not initially
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
Doesn't need to know what?
Anything about packages; the caller should just say “install postgres” and never hear about RPMs. (Notably, this would allow us to *transparently* switch from RPMs to Docker images—and even back the other way if necessary.)
startServices() # start the services restartServices()
# restart the services stopServices() # stop the services
The caller managing the server doesn‘t need to know that; this is an implementation detail of the role.
Same question.
Same answer: just say “start postgres” and never hear about systemd units. Especially when there *already* is start() and stop(), exposing the subcomponents of that API is rather redundant.
To be more clear about the two comments above, I’m not saying that the D-Bus *service* shouldn’t know about packages or systemd services, or that roles should explicitly implement start() and stop() instead of providing static data like package and service names. But these should *only* be visible in the Server role D-Bus service <-> individual role API (internal and free to be modified), not in the anybody <-> D-Bus service API (published and stable forever within that API version). Mirek
Stephen Gallagher sgallagh@redhat.com writes:
Yeah, we probably need getAvailableRoles()
The proposal had a "roles" property, isn't that enough?
I would also expect the service to implement the ObjectManager interface so that clients can list all objects and then find all roles by looking for the org.fedoraproject.ServiceManager1.Role interface.
services:a{sas} (ro) # services to be enabled and/or started: "enable": [s] and "start": [s]
It seems to me that the caller managing the server doesn‘t need to know that; this is an implementation detail of the role, but I could be persuaded that cockpit needs this for actionable status display.
Yes, Cockpit will need this for display purposes.
Well, hmm, the proposed API does also cover run-time state, so we might get away with just using that and ignoring systemd.
2014-06-03 16:14 GMT+02:00 Marius Vollmer marius.vollmer@redhat.com:
Stephen Gallagher sgallagh@redhat.com writes:
Yeah, we probably need getAvailableRoles()
The proposal had a "roles" property, isn't that enough?
Ah, true. (Though that makes it somewhat curious that one roel list is a property and another is a return value from a function.) Mirek
On 06/03/2014 04:19 PM, Miloslav Trmač wrote:
2014-06-03 16:14 GMT+02:00 Marius Vollmer <marius.vollmer@redhat.com mailto:marius.vollmer@redhat.com>:
Stephen Gallagher <sgallagh@redhat.com <mailto:sgallagh@redhat.com>> writes: > Yeah, we probably need getAvailableRoles() The proposal had a "roles" property, isn't that enough?
Ah, true. (Though that makes it somewhat curious that one roel list is a property and another is a return value from a function.) Mirek
With the property roles, you will get all roles. The consumer than has to loop over all roles to get the ones that are in active state.
With the method getActiveRoles this is done internally and only the roles that are active. With a general getRoleByState(state) this could be extended.
server mailing list server@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/server
server@lists.fedoraproject.org