49 lines
14 KiB
JSON
49 lines
14 KiB
JSON
{
|
|
"name": "smf",
|
|
"description": "A light weight resource provider (LWRP) for SMF (Service Management Facility)",
|
|
"long_description": "SMF\n===\n\n## Description\n\nService Management Facility (SMF) is a tool in many Illumos and Solaris-derived operating systems\nthat treats services as first class objects of the system. It provides an XML syntax for \ndeclaring how the system can interact with and control a service.\n\nThe SMF cookbook contains providers for creating or modifying a service within the SMF framework.\n\n\n## Requirements\n\nAny operating system that uses SMF, ie Solaris, SmartOS, OpenIndiana etc.\n\nThe `smf` provider depends on the `builder` gem, which can be installed\nvia the `smf::default` recipe.\n\nRequires the RBAC cookbook, which can be found at <https://supermarket.getchef.com/cookbooks/rbac>.\n\nProcesses can be run inside a project wrapper. In this case, look to the Resource Control cookbook,\nwhich can be found at <https://supermarket.getchef.com/cookbooks/resource-control>. Note that the SMF LWRP\ndoes not create or manage the project.\n\n\n## Basic Usage\n\nNote that we run the `smf::default` recipe before using LWRPs from this\ncookbook.\n\n```ruby\ninclude_recipe 'smf'\n\nsmf 'my-service' do\n user 'non-root-user'\n start_command 'my-service start'\n start_timeout 10\n stop_command 'pkill my-service'\n stop_timeout 5\n restart_command 'my-service restart'\n restart_timeout 60\n environment 'PATH' => '/home/non-root-user/bin',\n 'RAILS_ENV' => 'staging'\n locale 'C'\n manifest_type 'application'\n service_path '/var/svc/manifest'\n notifies :restart, 'service[my-service]'\nend\n\nservice 'my-service' do\n action :enable\nend\n\nservice 'my-service' do\n action :restart\nend\n```\n\n\n## Attributes\n\nOwnership:\n* `user` - User to run service commands as\n* `group` - Group to run service commands as\n\nRBAC\n* `authorization` - What management and value authorizations should be\n created for this service. Defaults to the service name.\n\nDependency management:\n* `include_default_dependencies` - Service should depend on file system\n and network services. Defaults to `true`. See [Dependencies](#dependencies)\n for more info.\n* `dependency` - an optional array of hashes signifying service and path\n dependencies for this service to run. See [Dependencies](#dependencies).\n\nProcess management:\n* `project` - Name of project to run commands in\n* `start_command`\n* `start_timeout`\n* `stop_command` - defaults to `:kill`, which basically means it will destroy every PID generated from the start command\n* `stop_timeout`\n* `restart_command` - defaults to `stop_command`, then `start_command`\n* `restart_timeout`\n* `refresh_command` - by default SMF treats this as `true`. This will be called when the SMF definition changes or\n when a `notify :reload, 'service[thing]'` is called.\n* `refresh_timeout`\n* `duration` - Can be either `contract`, `wait`, `transient` or\n `child`, but defaults to `contract`. See the [Duration](#duration) section below.\n* `environment` - Hash - Environment variables to set while running commands\n* `ignore` - Array - Faults to ignore in subprocesses. For example, \n if core dumps in children are handled by a master process and you \n don't want SMF thinking the service is exploding, you can ignore \n [\"core\", \"signal\"].\n* `privileges` - Array - An array of privileges to be allowed for started processes.\n Defaults to ['basic', 'net_privaddr']\n* `property_groups` - Hash - This should be in the form `{\"group name\" => {\"type\" => \"application\", \"key\" => \"value\", ...}}`\n* `working_directory` - PWD that SMF should cd to in order to run commands\n* `locale` - Character encoding to use (default \"C\")\n\nManifest/FMRI metadata:\n* `service_path` - defaults to `/var/svc/manifest`\n* `manifest_type` - defaults to `application`\n* `stability` - String - defaults to \"Evolving\". Valid options are\n \"Standard\", \"Stable\", \"Evolving\", \"Unstable\", \"External\" and\n \"Obsolete\"\n\nDeprecated:\n* `credentials_user` - deprecated in favor of `user`\n\n\n## Provider Actions\n\n### :install (default)\n\nThis will drop a manifest XML file into `#{service_path}/#{manifest_type}/#{name}.xml`. If there is already a service\nwith a name that is matched by `new_resource.name` then the FMRI of our manifest will be set to the FMRI of the \npre-existing service. In this case, our properties will be merged into the properties of the pre-existing service.\n\nIn this way, updates to recipes that use the SMF provider will not delete existing service properties, but will add \nor overwrite them.\n\nBecause of this, the SMF provider can be used to update properties for\nservices that are installed via a package manager.\n\n### :delete\n\nRemove an SMF definition. This stops the service if it is running.\n\n### :add_rbac\n\nThis uses the `rbac` cookbook to define permissions that can then be applied to a user. This can be useful when local\nusers should manage services that are added via packages.\n\n```ruby\nsmf \"nginx\" do\n action :add_rbac\nend\n\nrbac_auth \"Allow my user to manage nginx\" do\n user \"my_user\"\n auth \"nginx\"\nend\n```\n\n\n## Resource Notes\n\n### `user`, `working_directory` and `environment`\n\nSMF does a remarkably good job running services as delegated users, and removes a lot of pain if you configure a \nservice correctly. There are many examples online (blogs, etc) of users wrapping their services in shell scripts with \n`start`, `stop`, `restart` arguments. In general it seems as if the intention of these scripts is to take care of the\nproblem of setting environment variables and shelling out as another user.\n\nThe use of init scripts to wrap executables can be unnecessary with SMF, as it provides hooks for all of these use cases. \nWhen using `user`, SMF will assume that the `working_directory` is the user's home directory. This can be\neasily overwritten (to `/home/user/app/current` for a Rails application, for example). One thing to be careful of is \nthat shell profile files will not be loaded. For this reason, if environment variables (such as PATH) are different \non your system or require additional entries arbitrary key/values may be set using the `environment` attribute.\n\nAll things considered, one should think carefully about the need for an init script when working with SMF. For \nwell-behaved applications with simple configuration, an init script is overkill. Applications with endless command-line \noptions or that need a real login shell (for instance ruby applications that use RVM) an init script may make life\neasier.\n\n### Role Based Authorization\n\nBy default the SMF definition creates authorizations based on the\nservice name. The service user is then granted these authorizations. If\nthe service is named `asplosions`, then `solaris.smf.manage.asplosions`\nand `solaris.smf.value.asplosions` will be created.\n\nThe authorization can be changed by manually setting `authorization` on\nthe smf block:\n\n```ruby\nsmf 'asplosions' do\n user 'monkeyking'\n start_command 'asplode'\n authorization 'booms'\nend\n```\n\nThis can be helpful if there are many services configured on a single\nhost, as multiple services can be collapsed into the same\nauthorizations. For instance: https://illumos.org/issues/4968 \n\n### Dependencies\n\nSMF allows services to explicitly list their dependencies on other\nservices. Among other things, this ensures that services are enabled in\nthe proper order on boot, so that a service doesn't fail to start\nbecause another service has not yet been started.\n\nBy default, services created by the SMF LWRP depend on the following other services:\n* svc:/milestone/sysconfig\n* svc:/system/filesystem/local\n* svc:/milestone/name-services\n* svc:/milestone/network\n\nOn Solaris11, `svc:/milestone/sysconfig` is replaced with\n`svc:/milestone/config`.\n\nThese are configured with the attribute `include_default_dependencies`,\nwhich defaults to `true`.\n\nOther dependencies can be specified with the `dependencies` attribute,\nwhich takes an array of hashes as follows:\n\n```ruby\nsmf 'redis'\n\nsmf 'redis-6999' do\n start_command \"...\"\n dependencies [\n {name: 'redis', fmris: ['svc:/application/management/redis'],\n grouping: 'require_all', restart_on: 'restart', type: 'service'}\n ]\nend\n```\n\nValid options for grouping:\n* require_all - All listed FMRIs must be online\n* require_any - Any of the listed FMRIs must be online\n* exclude_all - None of the listed FMRIs can be online\n* optional_all - FMRIs are either online or unable to come online\n\nValid options for restart_on:\n* error - Hardware fault\n* restart - Restarts service if the depedency is restarted\n* refresh - Restarted if the dependency is restarted or refreshed for\n any reason\n* none - Don't do anything\n\nValid options for type:\n* service - expects dependency FMRIs to be other services ie: svc:/type/of/service:instance\n* path - expects FMRIs to be paths, ie file://localhost/etc/redis/redis.conf\n\nNote: the provider currently does not do any validation of these values. Also, type:path has not been extensively\ntested. Use this at your own risk, or improve the provider's compatibility with type:path and submit a pull request!\n\n### Duration\n\nThere are several different ways that SMF can track your service. By default it uses `contract`. \nBasically, this means that it will keep track of the PIDs of all daemonized processes generated from `start_command`.\nIf SMF sees that processes are cycling, it may try to restart the service. If things get too hectic, it\nmay think that your service is flailing and put it into maintenance mode. If this is normal for your service,\nfor instance if you have a master that occasionally reaps processes, you may want to specify additional\nconfiguration options.\n\nIf you have a job that you want managed by SMF, but which is not daemonized, another duration option is\n`transient`. In this mode, SMF will not watch any processes, but will expect that the main process exits cleanly.\nThis can be used, for instance, for a script that must be run at boot time, or for a script that you want to delegate\nto particular users with Role Based Access Control. In this case, the script can be registered with SMF to run as root,\nbut with the start_command delegated to your user.\n\nA third option is `wait`. This covers non-daemonized processes.\n\nA fourth option is `child`.\n\n### Ignore\n\nSometimes you have a case where your service behaves poorly. The Ruby server Unicorn, for example, has a master \nprocess that likes to kill its children. This causes core dumps that SMF will interpret to be a failing service.\nInstead you can `ignore [\"core\", \"signal\"]` and SMF will stop caring about core dumps.\n\n### Privileges\n\nSome system calls require privileges generally only granted to superusers or particular roles. In Solaris, an\nSMF definition can also set specific privileges for contracted processes.\n\nBy default the SMF provider will grant 'basic' and 'net_privaddr' permissions, but this can be set as follows:\n\n```ruby\nsmf 'elasticsearch' do\n start_command 'elasticsearch'\n privileges ['basic', 'proc_lock_memory']\nend\n```\n\nSee the (privileges man page)[https://www.illumos.org/man/5/privileges] for more information.\n\n### Property Groups\n\nProperty Groups are where you can store extra information for SMF to use later. They should be used in the\nfollowing format:\n\n```ruby\nsmf \"my-service\" do\n start_command \"do-something\"\n property_groups({\n \"config\" => {\n \"type\" => \"application\",\n \"my-property\" => \"property value\"\n }\n })\nend\n```\n\n`type` will default to `application`, and is used in the manifest XML to declare how the property group will be\nused. For this reason, `type` can not be used as a property name (ie variable).\n\nOne way to use property groups is to pass variables on to commands, as follows:\n\n```ruby\nrails_env = node[\"from-chef-environment\"][\"rails-env\"]\n\nsmf \"unicorn\" do\n start_command \"bundle exec unicorn_rails -c /home/app_user/app/current/config/%{config/rails_env} -E %{config/rails_env} -D\"\n start_timeout 300\n restart_command \":kill -SIGUSR2\"\n restart_timeout 300\n working_directory \"/home/app_user/app/current\"\n property_groups({\n \"config\" => {\n \"rails_env\" => rails_env\n }\n })\nend\n```\n\nThis is especially handy if you have a case where your commands may come from role attributes, but can\nonly work if they have access to variables set in an environment or computed in a recipe.\n\n### Stability\n\nThis is for reference more than anything, so that administrators of a service know what to expect of possible changes to \nthe service definition.\n\nSee: <http://www.cuddletech.com/blog/pivot/entry.php?id=182>\n\n\n## Working Examples\n\nPlease see the [examples](https://github.com/livinginthepast/smf/blob/master/EXAMPLES.md) page for\nexample usages.\n\n\n## Cookbook upgrades, possible side effects\n\nChanges to this cookbook may change the way that its internal checksums are generated for a service.\nIf you `notify :restart` any service from within the `smf` block or include a `refresh_command`, please\nbe aware that upgrading this cookbook may trigger a refresh or a registered notification on the first\nsubsequent chef run.\n\n## Contributing\n\n* fork\n* file an issue to track updates/communication\n* add tests\n* rebase master into your branch\n* issue a pull request\n\nPlease do not increment the cookbook version in a fork. Version updates\nwill be done on the master branch after any pull requests are merged.\n\nWhen upstream changes are added to the master branch while you are\nworking on a contribution, please rebase master into your branch and\nforce push. A pull request should be able to be merged through a\nfast-forward, without a merge commit.\n\n## Testing\n\n```bash\nbundle\nvagrant plugin install vagrant-smartos-zones\nbundle exec strainer test\n```\n",
|
|
"maintainer": "Eric Saxby",
|
|
"maintainer_email": "sax@livinginthepast.org",
|
|
"license": "MIT",
|
|
"platforms": {
|
|
"smartos": ">= 0.0.0"
|
|
},
|
|
"dependencies": {
|
|
"rbac": ">= 1.0.1"
|
|
},
|
|
"recommendations": {
|
|
|
|
},
|
|
"suggestions": {
|
|
"resource-control": ">= 0.0.0"
|
|
},
|
|
"conflicting": {
|
|
|
|
},
|
|
"providing": {
|
|
|
|
},
|
|
"replacing": {
|
|
|
|
},
|
|
"attributes": {
|
|
|
|
},
|
|
"groupings": {
|
|
|
|
},
|
|
"recipes": {
|
|
|
|
},
|
|
"version": "2.2.8",
|
|
"source_url": "",
|
|
"issues_url": "",
|
|
"privacy": false,
|
|
"chef_versions": [
|
|
|
|
],
|
|
"ohai_versions": [
|
|
|
|
]
|
|
}
|