diff --git a/NOTICE.txt b/NOTICE.txt index 6756b6a75db6..961402bbe7b2 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -514,8 +514,8 @@ This product includes software developed at CoreOS, Inc. -------------------------------------------------------------------- Dependency: github.com/coreos/go-systemd -Version: v18 -Revision: 9002847aa1425fb6ac49077c0a630b3b67e0fbfd +Version: v20 +Revision: fd7a80b32e1fc73e890fde45604ed5009dc817a3 License type (autodetected): Apache-2.0 ./vendor/github.com/coreos/go-systemd/LICENSE: -------------------------------------------------------------------- @@ -1917,6 +1917,38 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------- +Dependency: github.com/godbus/dbus +Revision: 37bf87eef99d69c4f1d3528bd66e3a87dc201472 +License type (autodetected): BSD-2-Clause +./vendor/github.com/godbus/dbus/LICENSE: +-------------------------------------------------------------------- +Copyright (c) 2013, Georg Reinke (), Google +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + -------------------------------------------------------------------- Dependency: github.com/gofrs/uuid Version: 3.1.1 diff --git a/metricbeat/_meta/fields.common.yml b/metricbeat/_meta/fields.common.yml index 6430a7279184..d65d152cc0b3 100644 --- a/metricbeat/_meta/fields.common.yml +++ b/metricbeat/_meta/fields.common.yml @@ -34,3 +34,13 @@ example: metricsets description: > The document type. Always set to "doc". + + - name: process.exit_code + type: long + description: the exit code of a process + - name: systemd.fragment_path + type: keyword + description: the location of the systemd unit path + - name: systemd.unit + type: keyword + description: the unit name of the systemd service diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 163d69526d06..1cc1642c062f 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -4282,6 +4282,33 @@ required: True -- +*`process.exit_code`*:: ++ +-- +the exit code of a process + +type: long + +-- + +*`systemd.fragment_path`*:: ++ +-- +the location of the systemd unit path + +type: keyword + +-- + +*`systemd.unit`*:: ++ +-- +the unit name of the systemd service + +type: keyword + +-- + [[exported-fields-consul]] == consul fields @@ -32214,6 +32241,146 @@ type: long Number of blocks on the device that are in sync, in 1024-byte blocks. +type: long + +-- + +[float] +=== service + +metrics for system services + + + +*`system.service.name`*:: ++ +-- +The name of the service + +type: keyword + +-- + +*`system.service.load_state`*:: ++ +-- +The load state of the service + +type: keyword + +-- + +*`system.service.state`*:: ++ +-- +The activity state of the service + +type: keyword + +-- + +*`system.service.sub_state`*:: ++ +-- +The sub-state of the service + +type: keyword + +-- + +*`system.service.state_since`*:: ++ +-- +The timestamp of the last state change. If the service is active and running, this is its uptime. + +type: date + +-- + +*`system.service.exec_code`*:: ++ +-- +The SIGCHLD code from the service's main process + +type: keyword + +-- + +[float] +=== resources + +system metrics associated with the service + + +*`system.service.resources.cpu.usage.ns`*:: ++ +-- +CPU usage in nanoseconds + +type: long + +-- + +*`system.service.resources.memory.usage.bytes`*:: ++ +-- +memory usage in bytes + +type: long + +-- + +*`system.service.resources.tasks.count`*:: ++ +-- +number of tasks associated with the service + +type: long + +-- + +[float] +=== network + +network resource usage + + +*`system.service.resources.network.in.bytes`*:: ++ +-- +bytes in + +type: long + +format: bytes + +-- + +*`system.service.resources.network.in.packets`*:: ++ +-- +packets in + +type: long + +format: bytes + +-- + +*`system.service.resources.network.out.packets`*:: ++ +-- +packets out + +type: long + +-- + +*`system.service.resources.network.out.bytes`*:: ++ +-- +bytes out + type: long -- diff --git a/metricbeat/docs/images/metricbeat-services-host.png b/metricbeat/docs/images/metricbeat-services-host.png new file mode 100644 index 000000000000..bc8d1814f8ba Binary files /dev/null and b/metricbeat/docs/images/metricbeat-services-host.png differ diff --git a/metricbeat/docs/modules/system.asciidoc b/metricbeat/docs/modules/system.asciidoc index 5cefc3021b00..f2d5751014ed 100644 --- a/metricbeat/docs/modules/system.asciidoc +++ b/metricbeat/docs/modules/system.asciidoc @@ -141,6 +141,8 @@ The following metricsets are available: * <> +* <> + * <> * <> @@ -171,6 +173,8 @@ include::system/process_summary.asciidoc[] include::system/raid.asciidoc[] +include::system/service.asciidoc[] + include::system/socket.asciidoc[] include::system/socket_summary.asciidoc[] diff --git a/metricbeat/docs/modules/system/service.asciidoc b/metricbeat/docs/modules/system/service.asciidoc new file mode 100644 index 000000000000..0f7fc1899808 --- /dev/null +++ b/metricbeat/docs/modules/system/service.asciidoc @@ -0,0 +1,23 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// + +[[metricbeat-metricset-system-service]] +=== System service metricset + +beta[] + +include::../../../module/system/service/_meta/docs.asciidoc[] + + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/system/service/_meta/data.json[] +---- diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index cb040b273b0e..29b886631a7c 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -185,7 +185,7 @@ This file is generated! See scripts/mage/docs_collector.go |<> beta[] |image:./images/icon-no.png[No prebuilt dashboards] | .1+| .1+| |<> beta[] |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | -.15+| .15+| |<> +.16+| .16+| |<> |<> |<> |<> @@ -197,6 +197,7 @@ This file is generated! See scripts/mage/docs_collector.go |<> |<> |<> +|<> beta[] |<> |<> |<> diff --git a/metricbeat/include/fields/fields.go b/metricbeat/include/fields/fields.go index 08e113a44d6a..1ee38f89f940 100644 --- a/metricbeat/include/fields/fields.go +++ b/metricbeat/include/fields/fields.go @@ -32,5 +32,5 @@ func init() { // AssetLibbeatFieldsYml returns asset data. // This is the base64 encoded gzipped contents of ../libbeat/fields.yml. func AssetLibbeatFieldsYml() string { - return "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" + return "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" } diff --git a/metricbeat/include/list_common.go b/metricbeat/include/list_common.go index a655dea57f33..26db25d57441 100644 --- a/metricbeat/include/list_common.go +++ b/metricbeat/include/list_common.go @@ -141,6 +141,7 @@ import ( _ "github.com/elastic/beats/metricbeat/module/system/process" _ "github.com/elastic/beats/metricbeat/module/system/process_summary" _ "github.com/elastic/beats/metricbeat/module/system/raid" + _ "github.com/elastic/beats/metricbeat/module/system/service" _ "github.com/elastic/beats/metricbeat/module/system/socket" _ "github.com/elastic/beats/metricbeat/module/system/socket_summary" _ "github.com/elastic/beats/metricbeat/module/system/uptime" diff --git a/metricbeat/module/system/_meta/config.yml b/metricbeat/module/system/_meta/config.yml index 3fe1693d3213..99c70442e523 100644 --- a/metricbeat/module/system/_meta/config.yml +++ b/metricbeat/module/system/_meta/config.yml @@ -12,6 +12,7 @@ #- core #- diskio #- socket + #- services process.include_top_n: by_cpu: 5 # include top 5 processes by CPU by_memory: 5 # include top 5 processes by memory diff --git a/metricbeat/module/system/_meta/kibana/7/dashboard/Metricbeat-Host-Services-overview.json b/metricbeat/module/system/_meta/kibana/7/dashboard/Metricbeat-Host-Services-overview.json new file mode 100644 index 000000000000..72033d930bb1 --- /dev/null +++ b/metricbeat/module/system/_meta/kibana/7/dashboard/Metricbeat-Host-Services-overview.json @@ -0,0 +1,831 @@ +{ + "objects": [ + { + "attributes": { + "description": "Overview of services on an individual host.", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": false, + "useMargins": true + }, + "panelsJSON": [ + { + "embeddableConfig": { + "title": "Running Services" + }, + "gridData": { + "h": 11, + "i": "023b7623-9610-47ee-a10c-64ee8d2ccfa1", + "w": 14, + "x": 0, + "y": 0 + }, + "panelIndex": "023b7623-9610-47ee-a10c-64ee8d2ccfa1", + "panelRefName": "panel_0", + "title": "Running Services", + "version": "7.4.0" + }, + { + "embeddableConfig": { + "title": "Service States" + }, + "gridData": { + "h": 11, + "i": "40ebab84-f48f-4060-a7af-3ffdf833ad3a", + "w": 12, + "x": 14, + "y": 0 + }, + "panelIndex": "40ebab84-f48f-4060-a7af-3ffdf833ad3a", + "panelRefName": "panel_1", + "title": "Service States", + "version": "7.4.0" + }, + { + "embeddableConfig": { + "title": "Service Sub-State" + }, + "gridData": { + "h": 11, + "i": "0ad1caa8-2a3f-4429-9631-42d1c57a9e64", + "w": 12, + "x": 26, + "y": 0 + }, + "panelIndex": "0ad1caa8-2a3f-4429-9631-42d1c57a9e64", + "panelRefName": "panel_2", + "title": "Service Sub-State", + "version": "7.4.0" + }, + { + "embeddableConfig": { + "title": "Return Codes Of Exited Services" + }, + "gridData": { + "h": 11, + "i": "9e37921b-da6f-464d-9683-5c9bd550640b", + "w": 10, + "x": 38, + "y": 0 + }, + "panelIndex": "9e37921b-da6f-464d-9683-5c9bd550640b", + "panelRefName": "panel_3", + "title": "Return Codes Of Exited Services", + "version": "7.4.0" + }, + { + "embeddableConfig": { + "title": "Top Services By Memory Usage" + }, + "gridData": { + "h": 11, + "i": "e3ec1fe3-a03a-466e-8bc2-69136e3e6302", + "w": 24, + "x": 0, + "y": 11 + }, + "panelIndex": "e3ec1fe3-a03a-466e-8bc2-69136e3e6302", + "panelRefName": "panel_4", + "title": "Top Services By Memory Usage", + "version": "7.4.0" + }, + { + "embeddableConfig": { + "title": "Top Services By Task Count" + }, + "gridData": { + "h": 11, + "i": "cc928f52-22c9-402d-a7a1-4f32720a4290", + "w": 24, + "x": 24, + "y": 11 + }, + "panelIndex": "cc928f52-22c9-402d-a7a1-4f32720a4290", + "panelRefName": "panel_5", + "title": "Top Services By Task Count", + "version": "7.4.0" + }, + { + "embeddableConfig": { + "title": "Service Memory Use Over Time" + }, + "gridData": { + "h": 14, + "i": "c83f16cd-286f-411b-bae9-bade176a8db2", + "w": 48, + "x": 0, + "y": 22 + }, + "panelIndex": "c83f16cd-286f-411b-bae9-bade176a8db2", + "panelRefName": "panel_6", + "title": "Service Memory Use Over Time", + "version": "7.4.0" + } + ], + "timeRestore": false, + "title": "[Metricbeat System] Host Services Overview", + "version": 1 + }, + "id": "c431f410-f9ac-11e9-90e8-1fb18e796788", + "migrationVersion": { + "dashboard": "7.3.0" + }, + "references": [ + { + "id": "a30871f0-f98f-11e9-90e8-1fb18e796788", + "name": "panel_0", + "type": "visualization" + }, + { + "id": "bb3a8720-f991-11e9-90e8-1fb18e796788", + "name": "panel_1", + "type": "visualization" + }, + { + "id": "e6e639e0-f992-11e9-90e8-1fb18e796788", + "name": "panel_2", + "type": "visualization" + }, + { + "id": "9c69cad0-f9b0-11e9-90e8-1fb18e796788", + "name": "panel_3", + "type": "visualization" + }, + { + "id": "8c071e20-f999-11e9-90e8-1fb18e796788", + "name": "panel_4", + "type": "visualization" + }, + { + "id": "4b254630-f998-11e9-90e8-1fb18e796788", + "name": "panel_5", + "type": "visualization" + }, + { + "id": "d3f51850-f9b6-11e9-90e8-1fb18e796788", + "name": "panel_6", + "type": "visualization" + } + ], + "type": "dashboard", + "updated_at": "2019-10-31T14:21:04.680Z", + "version": "WzE0NjksMV0=" + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.index", + "query": { + "language": "kuery", + "query": "" + } + } + }, + "title": "Running Services [Metricbeat System]", + "uiStateJSON": {}, + "version": 1, + "visState": { + "aggs": [ + { + "enabled": true, + "id": "1", + "params": { + "customLabel": "Running Services [Metricbeat Services]", + "field": "system.service.name" + }, + "schema": "metric", + "type": "cardinality" + } + ], + "params": { + "addLegend": false, + "addTooltip": true, + "dimensions": { + "metrics": [ + { + "accessor": 0, + "format": { + "id": "number", + "params": {} + }, + "type": "vis_dimension" + } + ] + }, + "metric": { + "colorSchema": "Green to Red", + "colorsRange": [ + { + "from": 0, + "to": 10000, + "type": "range" + } + ], + "invertColors": false, + "labels": { + "show": true + }, + "metricColorMode": "None", + "percentageMode": false, + "style": { + "bgColor": false, + "bgFill": "#000", + "fontSize": 60, + "labelColor": false, + "subText": "" + }, + "useRanges": false + }, + "type": "metric" + }, + "title": "Running Services [Metricbeat System]", + "type": "metric" + } + }, + "id": "a30871f0-f98f-11e9-90e8-1fb18e796788", + "migrationVersion": { + "visualization": "7.3.1" + }, + "references": [ + { + "id": "metricbeat-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2019-10-31T13:35:51.219Z", + "version": "WzE0NTAsMV0=" + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.index", + "query": { + "language": "kuery", + "query": "" + } + } + }, + "title": "Service States [Metricbeat System]", + "uiStateJSON": {}, + "version": 1, + "visState": { + "aggs": [ + { + "enabled": true, + "id": "1", + "params": { + "customLabel": "Service States [Metricbeat Services]" + }, + "schema": "metric", + "type": "count" + }, + { + "enabled": true, + "id": "2", + "params": { + "field": "system.service.state", + "missingBucket": false, + "missingBucketLabel": "Missing", + "order": "desc", + "orderBy": "1", + "otherBucket": false, + "otherBucketLabel": "Other", + "size": 5 + }, + "schema": "segment", + "type": "terms" + } + ], + "params": { + "addLegend": true, + "addTooltip": true, + "dimensions": { + "buckets": [ + { + "accessor": 0, + "aggType": "terms", + "format": { + "id": "terms", + "params": { + "id": "string", + "missingBucketLabel": "Missing", + "otherBucketLabel": "Other" + } + }, + "params": {} + } + ], + "metric": { + "accessor": 1, + "aggType": "count", + "format": { + "id": "number" + }, + "params": {} + } + }, + "isDonut": true, + "labels": { + "last_level": true, + "show": false, + "truncate": 100, + "values": true + }, + "legendPosition": "right", + "type": "pie" + }, + "title": "Service States [Metricbeat System]", + "type": "pie" + } + }, + "id": "bb3a8720-f991-11e9-90e8-1fb18e796788", + "migrationVersion": { + "visualization": "7.3.1" + }, + "references": [ + { + "id": "metricbeat-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2019-10-31T13:38:51.526Z", + "version": "WzE0NTIsMV0=" + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.index", + "query": { + "language": "kuery", + "query": "" + } + } + }, + "title": "Service Sub-State [Metricbeat System]", + "uiStateJSON": {}, + "version": 1, + "visState": { + "aggs": [ + { + "enabled": true, + "id": "1", + "params": { + "customLabel": "Service Sub-State [Metricbeat Services]" + }, + "schema": "metric", + "type": "count" + }, + { + "enabled": true, + "id": "2", + "params": { + "field": "system.service.sub_state", + "missingBucket": false, + "missingBucketLabel": "Missing", + "order": "desc", + "orderBy": "1", + "otherBucket": false, + "otherBucketLabel": "Other", + "size": 5 + }, + "schema": "segment", + "type": "terms" + } + ], + "params": { + "addLegend": true, + "addTooltip": true, + "dimensions": { + "buckets": [ + { + "accessor": 0, + "aggType": "terms", + "format": { + "id": "terms", + "params": { + "id": "string", + "missingBucketLabel": "Missing", + "otherBucketLabel": "Other" + } + }, + "params": {} + } + ], + "metric": { + "accessor": 1, + "aggType": "count", + "format": { + "id": "number" + }, + "params": {} + } + }, + "isDonut": true, + "labels": { + "last_level": true, + "show": false, + "truncate": 100, + "values": true + }, + "legendPosition": "right", + "type": "pie" + }, + "title": "Service Sub-State [Metricbeat System]", + "type": "pie" + } + }, + "id": "e6e639e0-f992-11e9-90e8-1fb18e796788", + "migrationVersion": { + "visualization": "7.3.1" + }, + "references": [ + { + "id": "metricbeat-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2019-10-31T13:40:09.336Z", + "version": "WzE0NTQsMV0=" + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "key": "metricset.name", + "negate": false, + "params": { + "query": "service" + }, + "type": "phrase", + "value": "service" + }, + "query": { + "match": { + "metricset.name": { + "query": "service", + "type": "phrase" + } + } + } + } + ], + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.index", + "query": { + "language": "kuery", + "query": "" + } + } + }, + "title": "Return Codes Of Exited Services [Metricbeat System]", + "uiStateJSON": {}, + "version": 1, + "visState": { + "aggs": [ + { + "enabled": true, + "id": "1", + "params": { + "customLabel": "Return Codes Of Exited Services [Metricbeat Services]" + }, + "schema": "metric", + "type": "count" + }, + { + "enabled": true, + "id": "2", + "params": { + "field": "process.exit_code", + "missingBucket": false, + "missingBucketLabel": "Missing", + "order": "desc", + "orderBy": "1", + "otherBucket": false, + "otherBucketLabel": "Other", + "size": 5 + }, + "schema": "segment", + "type": "terms" + } + ], + "params": { + "addLegend": true, + "addTooltip": true, + "dimensions": { + "buckets": [ + { + "accessor": 0, + "aggType": "terms", + "format": { + "id": "terms", + "params": { + "id": "number", + "missingBucketLabel": "Missing", + "otherBucketLabel": "Other" + } + }, + "params": {} + } + ], + "metric": { + "accessor": 1, + "aggType": "count", + "format": { + "id": "number" + }, + "params": {} + } + }, + "isDonut": true, + "labels": { + "last_level": true, + "show": false, + "truncate": 100, + "values": true + }, + "legendPosition": "right", + "type": "pie" + }, + "title": "Return Codes Of Exited Services [Metricbeat System]", + "type": "pie" + } + }, + "id": "9c69cad0-f9b0-11e9-90e8-1fb18e796788", + "migrationVersion": { + "visualization": "7.3.1" + }, + "references": [ + { + "id": "metricbeat-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + }, + { + "id": "metricbeat-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2019-10-31T14:03:44.126Z", + "version": "WzE0NjEsMV0=" + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "title": "Top Services By Memory Usage [Metricbeat System]", + "uiStateJSON": {}, + "version": 1, + "visState": { + "aggs": [], + "params": { + "axis_formatter": "number", + "axis_position": "left", + "axis_scale": "normal", + "bar_color_rules": [ + { + "id": "5af08c50-f998-11e9-ac67-272468589910" + } + ], + "default_index_pattern": "metricbeat-*", + "default_timefield": "@timestamp", + "id": "61ca57f0-469d-11e7-af02-69e470af7417", + "index_pattern": "", + "interval": "", + "isModelInvalid": false, + "series": [ + { + "axis_position": "right", + "chart_type": "line", + "color": "#68BC00", + "fill": 0.5, + "formatter": "bytes", + "id": "61ca57f1-469d-11e7-af02-69e470af7417", + "line_width": 1, + "metrics": [ + { + "field": "system.service.resources.memory.usage.bytes", + "id": "61ca57f2-469d-11e7-af02-69e470af7417", + "type": "avg" + } + ], + "point_size": 1, + "separate_axis": 0, + "split_mode": "terms", + "stacked": "none", + "terms_field": "system.service.name", + "terms_order_by": "61ca57f2-469d-11e7-af02-69e470af7417" + } + ], + "show_grid": 1, + "show_legend": 1, + "time_field": "", + "type": "top_n" + }, + "title": "Top Services By Memory Usage [Metricbeat System]", + "type": "metrics" + } + }, + "id": "8c071e20-f999-11e9-90e8-1fb18e796788", + "migrationVersion": { + "visualization": "7.3.1" + }, + "references": [], + "type": "visualization", + "updated_at": "2019-10-31T14:11:44.048Z", + "version": "WzE0NjMsMV0=" + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "title": "Top Services By Task Count [Metricbeat System]", + "uiStateJSON": {}, + "version": 1, + "visState": { + "aggs": [], + "params": { + "axis_formatter": "number", + "axis_position": "left", + "axis_scale": "normal", + "bar_color_rules": [ + { + "id": "3aeae000-f997-11e9-ac67-272468589910" + } + ], + "default_index_pattern": "metricbeat-*", + "default_timefield": "@timestamp", + "id": "61ca57f0-469d-11e7-af02-69e470af7417", + "index_pattern": "metricbeat-*", + "interval": "", + "isModelInvalid": false, + "series": [ + { + "axis_position": "right", + "chart_type": "line", + "color": "#68BC00", + "fill": 0.5, + "formatter": "number", + "hidden": false, + "id": "61ca57f1-469d-11e7-af02-69e470af7417", + "label": "", + "line_width": 1, + "metrics": [ + { + "field": "system.service.resources.tasks.count", + "id": "61ca57f2-469d-11e7-af02-69e470af7417", + "type": "avg" + } + ], + "point_size": 1, + "separate_axis": 0, + "split_mode": "terms", + "stacked": "none", + "terms_field": "system.service.name", + "terms_order_by": "61ca57f2-469d-11e7-af02-69e470af7417" + } + ], + "show_grid": 1, + "show_legend": 1, + "time_field": "", + "type": "top_n" + }, + "title": "Top Services By Task Count [Metricbeat System]", + "type": "metrics" + } + }, + "id": "4b254630-f998-11e9-90e8-1fb18e796788", + "migrationVersion": { + "visualization": "7.3.1" + }, + "references": [], + "type": "visualization", + "updated_at": "2019-10-31T14:14:42.665Z", + "version": "WzE0NjUsMV0=" + }, + { + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "title": "Service Memory Use Over Time [Metricbeat System]", + "uiStateJSON": {}, + "version": 1, + "visState": { + "aggs": [], + "params": { + "axis_formatter": "number", + "axis_position": "left", + "axis_scale": "normal", + "default_index_pattern": "metricbeat-*", + "default_timefield": "@timestamp", + "id": "61ca57f0-469d-11e7-af02-69e470af7417", + "index_pattern": "", + "interval": "", + "isModelInvalid": false, + "series": [ + { + "axis_position": "right", + "chart_type": "line", + "color": "rgba(244,78,59,1)", + "fill": "0", + "formatter": "bytes", + "id": "61ca57f1-469d-11e7-af02-69e470af7417", + "label": "", + "line_width": 1, + "metrics": [ + { + "field": "system.service.resources.memory.usage.bytes", + "id": "61ca57f2-469d-11e7-af02-69e470af7417", + "type": "avg" + } + ], + "point_size": 1, + "separate_axis": 0, + "split_color_mode": "rainbow", + "split_mode": "terms", + "stacked": "none", + "terms_field": "system.service.name", + "terms_order_by": "61ca57f2-469d-11e7-af02-69e470af7417", + "terms_size": "5", + "type": "timeseries" + } + ], + "show_grid": 1, + "show_legend": 1, + "time_field": "", + "type": "timeseries" + }, + "title": "Service Memory Use Over Time [Metricbeat System]", + "type": "metrics" + } + }, + "id": "d3f51850-f9b6-11e9-90e8-1fb18e796788", + "migrationVersion": { + "visualization": "7.3.1" + }, + "references": [], + "type": "visualization", + "updated_at": "2019-10-31T14:18:54.802Z", + "version": "WzE0NjcsMV0=" + } + ], + "version": "7.4.0" +} diff --git a/metricbeat/module/system/fields.go b/metricbeat/module/system/fields.go index 146a5774bd4c..b6702fc02e96 100644 --- a/metricbeat/module/system/fields.go +++ b/metricbeat/module/system/fields.go @@ -32,5 +32,5 @@ func init() { // AssetSystem returns asset data. // This is the base64 encoded gzipped contents of ../metricbeat/module/system. func AssetSystem() string { - return "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" + return "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" } diff --git a/metricbeat/module/system/service/_meta/data.json b/metricbeat/module/system/service/_meta/data.json new file mode 100644 index 000000000000..12f3fae8231b --- /dev/null +++ b/metricbeat/module/system/service/_meta/data.json @@ -0,0 +1,41 @@ +{ + "@timestamp": "2017-10-12T08:05:34.853Z", + "event": { + "dataset": "system.service", + "duration": 115000, + "module": "system" + }, + "metricset": { + "name": "service", + "period": 10000 + }, + "process": { + "pid": 811 + }, + "service": { + "type": "system" + }, + "system": { + "service": { + "load_state": "loaded", + "name": "NetworkManager.service", + "resources": { + "memory": { + "usage": { + "bytes": 15646720 + } + }, + "tasks": { + "count": 4 + } + }, + "state": "active", + "state_since": "2019-10-18T21:24:57.581561-07:00", + "sub_state": "running" + } + }, + "systemd": { + "fragment_path": "/usr/lib/systemd/system/NetworkManager.service", + "unit": "NetworkManager.service" + } +} \ No newline at end of file diff --git a/metricbeat/module/system/service/_meta/docs.asciidoc b/metricbeat/module/system/service/_meta/docs.asciidoc new file mode 100644 index 000000000000..1cb512dc7cdc --- /dev/null +++ b/metricbeat/module/system/service/_meta/docs.asciidoc @@ -0,0 +1,23 @@ +The `service` metricset reports on the status of systemd services. + +This metricset is available on: + +- Linux + +[float] +== systemd resource accounting and process metrics + +If systemd resource accounting is enabled, this metricset will report any resources tracked by systemd. On most distributions, `tasks` and `memory` are the only resources with accounting enabled by default. +For more information, https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html[see the systemd manual pages]. + +[float] +=== Configuration + +*`service.state_filter`* - A list of service states to filter by. This can be any of the states or sub-states known to systemd. + +[float] +=== Dashboard + +The system service metricset comes with a predefined dashboard. For example: + +image::./images/metricbeat-services-host.png[] \ No newline at end of file diff --git a/metricbeat/module/system/service/_meta/fields.yml b/metricbeat/module/system/service/_meta/fields.yml new file mode 100644 index 000000000000..529c4b01f97d --- /dev/null +++ b/metricbeat/module/system/service/_meta/fields.yml @@ -0,0 +1,56 @@ +- name: service + type: group + release: beta + description: > + metrics for system services + fields: + - name: name + type: keyword + description: The name of the service + - name: load_state + type: keyword + description: The load state of the service + - name: state + type: keyword + description: The activity state of the service + - name: sub_state + type: keyword + description: The sub-state of the service + - name: state_since + type: date + description: The timestamp of the last state change. If the service is active and running, this is its uptime. + - name: exec_code + type: keyword + description: The SIGCHLD code from the service's main process + - name: resources + type: group + description: system metrics associated with the service + fields: + - name: cpu.usage.ns + type: long + description: CPU usage in nanoseconds + - name: memory.usage.bytes + type: long + description: memory usage in bytes + - name: tasks.count + type: long + description: number of tasks associated with the service + - name: network + type: group + description: network resource usage + fields: + - name: in.bytes + type: long + format: bytes + description: bytes in + - name: in.packets + type: long + format: bytes + description: packets in + - name: out.packets + type: long + description: packets out + - name: out.bytes + type: long + description: bytes out + diff --git a/metricbeat/module/system/service/data.go b/metricbeat/module/system/service/data.go new file mode 100644 index 000000000000..36c143df63c8 --- /dev/null +++ b/metricbeat/module/system/service/data.go @@ -0,0 +1,224 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//+build !netbsd + +package service + +import ( + "time" + + "github.com/coreos/go-systemd/dbus" + "github.com/pkg/errors" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/metricbeat/mb" +) + +// Properties is a struct representation of the dbus returns from GetAllProperties +type Properties struct { + ExecMainCode int32 + ExecMainStatus int32 + ExecMainPID uint32 + // accounting + CPUAccounting bool + MemoryAccounting bool + TasksAccounting bool + IPAccounting bool + // metrics + CPUUsageNSec int64 + MemoryCurrent int64 + TasksCurrent int64 + IPIngressPackets int64 + IPIngressBytes int64 + IPEgressPackets int64 + IPEgressBytes int64 + // timestamps + ActiveEnterTimestamp uint64 + InactiveEnterTimestamp uint64 + InactiveExitTimestamp uint64 + ActiveExitTimestamp uint64 + // Meta + FragmentPath string +} + +// formProperties gets properties for the systemd service and returns a MapStr with useful data +func formProperties(unit dbus.UnitStatus, props Properties) (mb.Event, error) { + timeSince, err := timeSince(props, unit.ActiveState) + if err != nil { + return mb.Event{}, errors.Wrap(err, "error getting timestamp") + } + + event := mb.Event{ + RootFields: common.MapStr{}, + } + msData := common.MapStr{ + "name": unit.Name, + "load_state": unit.LoadState, + "state": unit.ActiveState, + "sub_state": unit.SubState, + } + + //most of the properties values are context-dependent. + //If things aren't running/haven't run/etc than a lot of the values should be ignored. + + //Even systemd doesn't check the substate, leading to a lot of odd `Memory: 0B` lines in `systemctl status` + //Ignore the resource accounting if a service has exited + if unit.ActiveState == "active" && unit.SubState != "exited" { + msData["resources"] = getMetricsFromServivce(props) + } + + var childProc = common.MapStr{} + childData := false + //anything less than 1 isn't a valid SIGCHLD code + if props.ExecMainCode > 0 { + childData = true + msData["exec_code"] = translateChild(props.ExecMainCode) + childProc["exit_code"] = props.ExecMainStatus + } + + //only send timestamp if it's valid + if timeSince != 0 { + msData["state_since"] = time.Unix(0, timeSince) + } + + //only prints PID data if we have a PID + if props.ExecMainPID > 0 { + childData = true + childProc["pid"] = props.ExecMainPID + } + + if childData { + event.RootFields["process"] = childProc + } + if props.IPAccounting { + event.RootFields["network"] = common.MapStr{ + "packets": props.IPIngressPackets + props.IPEgressPackets, + "bytes": props.IPIngressBytes + props.IPEgressBytes, + } + } + event.RootFields["systemd"] = common.MapStr{ + "unit": unit.Name, + "fragment_path": props.FragmentPath, + } + + event.MetricSetFields = msData + + return event, nil +} + +// getMetricsFromServivce checks what accounting we have enabled and uses that to determine what metrics we can send back to the user +func getMetricsFromServivce(props Properties) common.MapStr { + metrics := common.MapStr{} + + if props.CPUAccounting { + metrics["cpu"] = common.MapStr{ + "usage": common.MapStr{ + "nsec": props.CPUUsageNSec, + }, + } + } + + if props.MemoryAccounting { + metrics["memory"] = common.MapStr{ + "usage": common.MapStr{ + "bytes": props.MemoryCurrent, + }, + } + } + + if props.TasksAccounting { + metrics["tasks"] = common.MapStr{ + "count": props.TasksCurrent, + } + } + + if props.IPAccounting { + metrics["network"] = common.MapStr{ + "in": common.MapStr{ + "packets": props.IPIngressPackets, + "bytes": props.IPIngressBytes, + }, + "out": common.MapStr{ + "packets": props.IPEgressPackets, + "bytes": props.IPEgressBytes, + }, + } + } + + return metrics +} + +// translateChild translates the SIGCHILD code that systemd gets from the MainPID under its control into a string value. +// Normally this shows up in systemctl status like this: Main PID: 5305 (code=exited, status=0/SUCCESS) +// This mapping of SIGCHILD int codes comes from the kernel. systemd does something similar to turn them into pretty strings +func translateChild(code int32) string { + /* + CLD_EXITED: 1 + CLD_KILLED: 2 + CLD_DUMPED: 3 + CLD_TRAPPED: 4 + CLD_STOPPED: 5 + CLD_CONTINUED: 6 + */ + switch code { + case 1: + return "exited" + case 2: + return "killed" + case 3: + return "dumped" + case 4: + return "trapped" + case 5: + return "stopped" + case 6: + return "continued" + default: + return "unknown" + } + +} + +// timeSince emulates the behavior of `systemctl status` with regards to reporting time: +// "Active: inactive (dead) since Sat 2019-10-19 16:31:25 PDT;"" +// The dbus properties data contains a number of different timestamps, which one systemd reports depends on the unit state +func timeSince(props Properties, state string) (int64, error) { + + var ts uint64 + //normally we would want to check these values before we cast, + //but checking the state before we access `props` insures the values will be there. + switch state { + case "reloading", "active": + ts = props.ActiveEnterTimestamp + case "failed", "inactive": + ts = props.InactiveEnterTimestamp + case "activating": + ts = props.InactiveExitTimestamp + default: + ts = props.ActiveExitTimestamp + } + + //That second number is "USEC_INFINITY" which seems to a thing systemd cares about + if ts <= 0 || ts == 18446744073709551615 { + return 0, nil + } + + //convert from usec + return int64(ts) * 1000, nil + +} diff --git a/metricbeat/module/system/service/doc.go b/metricbeat/module/system/service/doc.go new file mode 100644 index 000000000000..5ba13a7ebeb8 --- /dev/null +++ b/metricbeat/module/system/service/doc.go @@ -0,0 +1,18 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package service diff --git a/metricbeat/module/system/service/service.go b/metricbeat/module/system/service/service.go new file mode 100644 index 000000000000..ca5db61319b2 --- /dev/null +++ b/metricbeat/module/system/service/service.go @@ -0,0 +1,123 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//+build !netbsd + +package service + +import ( + "github.com/coreos/go-systemd/dbus" + "github.com/mitchellh/mapstructure" + "github.com/pkg/errors" + + "github.com/elastic/beats/libbeat/common/cfgwarn" + "github.com/elastic/beats/metricbeat/mb" +) + +// Config stores the config object +type Config struct { + StateFilter []string `config:"service.state_filter"` +} + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet("system", "service", New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + conn *dbus.Conn + cfg Config +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The system service metricset is beta.") + + var config Config + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + conn, err := dbus.New() + if err != nil { + return nil, errors.Wrap(err, "error connecting to dbus") + } + + return &MetricSet{ + BaseMetricSet: base, + conn: conn, + cfg: config, + }, nil +} + +// Fetch methods implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + units, err := m.conn.ListUnitsByPatterns(m.cfg.StateFilter, []string{"*.service"}) + if err != nil { + return errors.Wrap(err, "error getting list of running units") + } + + for _, unit := range units { + //Skip what are basically errors dude to systemd's declarative dependency system + if unit.LoadState == "not-found" { + continue + } + + props, err := getProps(m.conn, unit.Name) + if err != nil { + m.Logger().Errorf("error getting properties for service: %s", err) + continue + } + + event, err := formProperties(unit, props) + if err != nil { + m.Logger().Errorf("Error getting properties for systemd service %s: %s", unit.Name, err) + continue + } + + isOpen := report.Event(event) + if !isOpen { + return nil + } + + } + return nil +} + +// Get Properties for a given unit, cast to a struct +func getProps(conn *dbus.Conn, unit string) (Properties, error) { + rawProps, err := conn.GetAllProperties(unit) + if err != nil { + return Properties{}, errors.Wrap(err, "error getting list of running units") + } + parsed := Properties{} + if err := mapstructure.Decode(rawProps, &parsed); err != nil { + return parsed, errors.Wrap(err, "error decoding properties") + } + return parsed, nil +} diff --git a/metricbeat/module/system/service/service_test.go b/metricbeat/module/system/service/service_test.go new file mode 100644 index 000000000000..0335bc11129c --- /dev/null +++ b/metricbeat/module/system/service/service_test.go @@ -0,0 +1,74 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//+build !netbsd + +package service + +import ( + "testing" + "time" + + "github.com/coreos/go-systemd/dbus" + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/libbeat/common" +) + +func TestFormProps(t *testing.T) { + testUnit := dbus.UnitStatus{ + Name: "test.service", + LoadState: "loaded", + ActiveState: "active", + SubState: "running", + } + testprops := Properties{ + ExecMainPID: 0, + ExecMainStatus: 0, + ExecMainCode: 1, + ActiveEnterTimestamp: 1571850129000000, + IPAccounting: true, + IPEgressBytes: 100, + IPIngressBytes: 50, + IPEgressPackets: 100, + IPIngressPackets: 50, + } + event, err := formProperties(testUnit, testprops) + assert.NoError(t, err) + + testEvent := common.MapStr{ + "state": "active", + "exec_code": "exited", + "load_state": "loaded", + "name": "test.service", + "state_since": time.Unix(0, 1571850129000000*1000), + "sub_state": "running", + "resources": common.MapStr{"network": common.MapStr{ + "in": common.MapStr{ + "bytes": 50, + "packets": 50}, + "out": common.MapStr{ + "bytes": 100, + "packets": 100}, + }, + }, + } + + assert.NotEmpty(t, event.MetricSetFields["resources"]) + assert.Equal(t, event.MetricSetFields["state_since"], testEvent["state_since"]) + assert.NotEmpty(t, event.RootFields) +} diff --git a/metricbeat/modules.d/system.yml b/metricbeat/modules.d/system.yml index aa8dae552632..ea8126d94e52 100644 --- a/metricbeat/modules.d/system.yml +++ b/metricbeat/modules.d/system.yml @@ -15,6 +15,7 @@ #- core #- diskio #- socket + #- services process.include_top_n: by_cpu: 5 # include top 5 processes by CPU by_memory: 5 # include top 5 processes by memory diff --git a/vendor/github.com/coreos/go-systemd/dbus/dbus.go b/vendor/github.com/coreos/go-systemd/dbus/dbus.go new file mode 100644 index 000000000000..f652582e658f --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/dbus/dbus.go @@ -0,0 +1,240 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Integration with the systemd D-Bus API. See http://www.freedesktop.org/wiki/Software/systemd/dbus/ +package dbus + +import ( + "encoding/hex" + "fmt" + "os" + "strconv" + "strings" + "sync" + + "github.com/godbus/dbus" +) + +const ( + alpha = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ` + num = `0123456789` + alphanum = alpha + num + signalBuffer = 100 +) + +// needsEscape checks whether a byte in a potential dbus ObjectPath needs to be escaped +func needsEscape(i int, b byte) bool { + // Escape everything that is not a-z-A-Z-0-9 + // Also escape 0-9 if it's the first character + return strings.IndexByte(alphanum, b) == -1 || + (i == 0 && strings.IndexByte(num, b) != -1) +} + +// PathBusEscape sanitizes a constituent string of a dbus ObjectPath using the +// rules that systemd uses for serializing special characters. +func PathBusEscape(path string) string { + // Special case the empty string + if len(path) == 0 { + return "_" + } + n := []byte{} + for i := 0; i < len(path); i++ { + c := path[i] + if needsEscape(i, c) { + e := fmt.Sprintf("_%x", c) + n = append(n, []byte(e)...) + } else { + n = append(n, c) + } + } + return string(n) +} + +// pathBusUnescape is the inverse of PathBusEscape. +func pathBusUnescape(path string) string { + if path == "_" { + return "" + } + n := []byte{} + for i := 0; i < len(path); i++ { + c := path[i] + if c == '_' && i+2 < len(path) { + res, err := hex.DecodeString(path[i+1 : i+3]) + if err == nil { + n = append(n, res...) + } + i += 2 + } else { + n = append(n, c) + } + } + return string(n) +} + +// Conn is a connection to systemd's dbus endpoint. +type Conn struct { + // sysconn/sysobj are only used to call dbus methods + sysconn *dbus.Conn + sysobj dbus.BusObject + + // sigconn/sigobj are only used to receive dbus signals + sigconn *dbus.Conn + sigobj dbus.BusObject + + jobListener struct { + jobs map[dbus.ObjectPath]chan<- string + sync.Mutex + } + subStateSubscriber struct { + updateCh chan<- *SubStateUpdate + errCh chan<- error + sync.Mutex + ignore map[dbus.ObjectPath]int64 + cleanIgnore int64 + } + propertiesSubscriber struct { + updateCh chan<- *PropertiesUpdate + errCh chan<- error + sync.Mutex + } +} + +// New establishes a connection to any available bus and authenticates. +// Callers should call Close() when done with the connection. +func New() (*Conn, error) { + conn, err := NewSystemConnection() + if err != nil && os.Geteuid() == 0 { + return NewSystemdConnection() + } + return conn, err +} + +// NewSystemConnection establishes a connection to the system bus and authenticates. +// Callers should call Close() when done with the connection +func NewSystemConnection() (*Conn, error) { + return NewConnection(func() (*dbus.Conn, error) { + return dbusAuthHelloConnection(dbus.SystemBusPrivate) + }) +} + +// NewUserConnection establishes a connection to the session bus and +// authenticates. This can be used to connect to systemd user instances. +// Callers should call Close() when done with the connection. +func NewUserConnection() (*Conn, error) { + return NewConnection(func() (*dbus.Conn, error) { + return dbusAuthHelloConnection(dbus.SessionBusPrivate) + }) +} + +// NewSystemdConnection establishes a private, direct connection to systemd. +// This can be used for communicating with systemd without a dbus daemon. +// Callers should call Close() when done with the connection. +func NewSystemdConnection() (*Conn, error) { + return NewConnection(func() (*dbus.Conn, error) { + // We skip Hello when talking directly to systemd. + return dbusAuthConnection(func(opts ...dbus.ConnOption) (*dbus.Conn, error) { + return dbus.Dial("unix:path=/run/systemd/private") + }) + }) +} + +// Close closes an established connection +func (c *Conn) Close() { + c.sysconn.Close() + c.sigconn.Close() +} + +// NewConnection establishes a connection to a bus using a caller-supplied function. +// This allows connecting to remote buses through a user-supplied mechanism. +// The supplied function may be called multiple times, and should return independent connections. +// The returned connection must be fully initialised: the org.freedesktop.DBus.Hello call must have succeeded, +// and any authentication should be handled by the function. +func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) { + sysconn, err := dialBus() + if err != nil { + return nil, err + } + + sigconn, err := dialBus() + if err != nil { + sysconn.Close() + return nil, err + } + + c := &Conn{ + sysconn: sysconn, + sysobj: systemdObject(sysconn), + sigconn: sigconn, + sigobj: systemdObject(sigconn), + } + + c.subStateSubscriber.ignore = make(map[dbus.ObjectPath]int64) + c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string) + + // Setup the listeners on jobs so that we can get completions + c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, + "type='signal', interface='org.freedesktop.systemd1.Manager', member='JobRemoved'") + + c.dispatch() + return c, nil +} + +// GetManagerProperty returns the value of a property on the org.freedesktop.systemd1.Manager +// interface. The value is returned in its string representation, as defined at +// https://developer.gnome.org/glib/unstable/gvariant-text.html +func (c *Conn) GetManagerProperty(prop string) (string, error) { + variant, err := c.sysobj.GetProperty("org.freedesktop.systemd1.Manager." + prop) + if err != nil { + return "", err + } + return variant.String(), nil +} + +func dbusAuthConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) { + conn, err := createBus() + if err != nil { + return nil, err + } + + // Only use EXTERNAL method, and hardcode the uid (not username) + // to avoid a username lookup (which requires a dynamically linked + // libc) + methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))} + + err = conn.Auth(methods) + if err != nil { + conn.Close() + return nil, err + } + + return conn, nil +} + +func dbusAuthHelloConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) { + conn, err := dbusAuthConnection(createBus) + if err != nil { + return nil, err + } + + if err = conn.Hello(); err != nil { + conn.Close() + return nil, err + } + + return conn, nil +} + +func systemdObject(conn *dbus.Conn) dbus.BusObject { + return conn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1")) +} diff --git a/vendor/github.com/coreos/go-systemd/dbus/methods.go b/vendor/github.com/coreos/go-systemd/dbus/methods.go new file mode 100644 index 000000000000..5859583eb245 --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/dbus/methods.go @@ -0,0 +1,600 @@ +// Copyright 2015, 2018 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dbus + +import ( + "errors" + "fmt" + "path" + "strconv" + + "github.com/godbus/dbus" +) + +func (c *Conn) jobComplete(signal *dbus.Signal) { + var id uint32 + var job dbus.ObjectPath + var unit string + var result string + dbus.Store(signal.Body, &id, &job, &unit, &result) + c.jobListener.Lock() + out, ok := c.jobListener.jobs[job] + if ok { + out <- result + delete(c.jobListener.jobs, job) + } + c.jobListener.Unlock() +} + +func (c *Conn) startJob(ch chan<- string, job string, args ...interface{}) (int, error) { + if ch != nil { + c.jobListener.Lock() + defer c.jobListener.Unlock() + } + + var p dbus.ObjectPath + err := c.sysobj.Call(job, 0, args...).Store(&p) + if err != nil { + return 0, err + } + + if ch != nil { + c.jobListener.jobs[p] = ch + } + + // ignore error since 0 is fine if conversion fails + jobID, _ := strconv.Atoi(path.Base(string(p))) + + return jobID, nil +} + +// StartUnit enqueues a start job and depending jobs, if any (unless otherwise +// specified by the mode string). +// +// Takes the unit to activate, plus a mode string. The mode needs to be one of +// replace, fail, isolate, ignore-dependencies, ignore-requirements. If +// "replace" the call will start the unit and its dependencies, possibly +// replacing already queued jobs that conflict with this. If "fail" the call +// will start the unit and its dependencies, but will fail if this would change +// an already queued job. If "isolate" the call will start the unit in question +// and terminate all units that aren't dependencies of it. If +// "ignore-dependencies" it will start a unit but ignore all its dependencies. +// If "ignore-requirements" it will start a unit but only ignore the +// requirement dependencies. It is not recommended to make use of the latter +// two options. +// +// If the provided channel is non-nil, a result string will be sent to it upon +// job completion: one of done, canceled, timeout, failed, dependency, skipped. +// done indicates successful execution of a job. canceled indicates that a job +// has been canceled before it finished execution. timeout indicates that the +// job timeout was reached. failed indicates that the job failed. dependency +// indicates that a job this job has been depending on failed and the job hence +// has been removed too. skipped indicates that a job was skipped because it +// didn't apply to the units current state. +// +// If no error occurs, the ID of the underlying systemd job will be returned. There +// does exist the possibility for no error to be returned, but for the returned job +// ID to be 0. In this case, the actual underlying ID is not 0 and this datapoint +// should not be considered authoritative. +// +// If an error does occur, it will be returned to the user alongside a job ID of 0. +func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode) +} + +// StopUnit is similar to StartUnit but stops the specified unit rather +// than starting it. +func (c *Conn) StopUnit(name string, mode string, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode) +} + +// ReloadUnit reloads a unit. Reloading is done only if the unit is already running and fails otherwise. +func (c *Conn) ReloadUnit(name string, mode string, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadUnit", name, mode) +} + +// RestartUnit restarts a service. If a service is restarted that isn't +// running it will be started. +func (c *Conn) RestartUnit(name string, mode string, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.RestartUnit", name, mode) +} + +// TryRestartUnit is like RestartUnit, except that a service that isn't running +// is not affected by the restart. +func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode) +} + +// ReloadOrRestartUnit attempts a reload if the unit supports it and use a restart +// otherwise. +func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode) +} + +// ReloadOrTryRestartUnit attempts a reload if the unit supports it and use a "Try" +// flavored restart otherwise. +func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode) +} + +// StartTransientUnit() may be used to create and start a transient unit, which +// will be released as soon as it is not running or referenced anymore or the +// system is rebooted. name is the unit name including suffix, and must be +// unique. mode is the same as in StartUnit(), properties contains properties +// of the unit. +func (c *Conn) StartTransientUnit(name string, mode string, properties []Property, ch chan<- string) (int, error) { + return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0)) +} + +// KillUnit takes the unit name and a UNIX signal number to send. All of the unit's +// processes are killed. +func (c *Conn) KillUnit(name string, signal int32) { + c.sysobj.Call("org.freedesktop.systemd1.Manager.KillUnit", 0, name, "all", signal).Store() +} + +// ResetFailedUnit resets the "failed" state of a specific unit. +func (c *Conn) ResetFailedUnit(name string) error { + return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store() +} + +// SystemState returns the systemd state. Equivalent to `systemctl is-system-running`. +func (c *Conn) SystemState() (*Property, error) { + var err error + var prop dbus.Variant + + obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1") + err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop) + if err != nil { + return nil, err + } + + return &Property{Name: "SystemState", Value: prop}, nil +} + +// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface +func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) { + var err error + var props map[string]dbus.Variant + + if !path.IsValid() { + return nil, fmt.Errorf("invalid unit name: %v", path) + } + + obj := c.sysconn.Object("org.freedesktop.systemd1", path) + err = obj.Call("org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props) + if err != nil { + return nil, err + } + + out := make(map[string]interface{}, len(props)) + for k, v := range props { + out[k] = v.Value() + } + + return out, nil +} + +// GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties. +func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) { + path := unitPath(unit) + return c.getProperties(path, "org.freedesktop.systemd1.Unit") +} + +// GetUnitPathProperties takes the (escaped) unit path and returns all of its dbus object properties. +func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) { + return c.getProperties(path, "org.freedesktop.systemd1.Unit") +} + +// GetAllProperties takes the (unescaped) unit name and returns all of its dbus object properties. +func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) { + path := unitPath(unit) + return c.getProperties(path, "") +} + +func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) { + var err error + var prop dbus.Variant + + path := unitPath(unit) + if !path.IsValid() { + return nil, errors.New("invalid unit name: " + unit) + } + + obj := c.sysconn.Object("org.freedesktop.systemd1", path) + err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, dbusInterface, propertyName).Store(&prop) + if err != nil { + return nil, err + } + + return &Property{Name: propertyName, Value: prop}, nil +} + +func (c *Conn) GetUnitProperty(unit string, propertyName string) (*Property, error) { + return c.getProperty(unit, "org.freedesktop.systemd1.Unit", propertyName) +} + +// GetServiceProperty returns property for given service name and property name +func (c *Conn) GetServiceProperty(service string, propertyName string) (*Property, error) { + return c.getProperty(service, "org.freedesktop.systemd1.Service", propertyName) +} + +// GetUnitTypeProperties returns the extra properties for a unit, specific to the unit type. +// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope +// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit +func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) { + path := unitPath(unit) + return c.getProperties(path, "org.freedesktop.systemd1."+unitType) +} + +// SetUnitProperties() may be used to modify certain unit properties at runtime. +// Not all properties may be changed at runtime, but many resource management +// settings (primarily those in systemd.cgroup(5)) may. The changes are applied +// instantly, and stored on disk for future boots, unless runtime is true, in which +// case the settings only apply until the next reboot. name is the name of the unit +// to modify. properties are the settings to set, encoded as an array of property +// name and value pairs. +func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Property) error { + return c.sysobj.Call("org.freedesktop.systemd1.Manager.SetUnitProperties", 0, name, runtime, properties).Store() +} + +func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) { + return c.getProperty(unit, "org.freedesktop.systemd1."+unitType, propertyName) +} + +type UnitStatus struct { + Name string // The primary unit name as string + Description string // The human readable description string + LoadState string // The load state (i.e. whether the unit file has been loaded successfully) + ActiveState string // The active state (i.e. whether the unit is currently started or not) + SubState string // The sub state (a more fine-grained version of the active state that is specific to the unit type, which the active state is not) + Followed string // A unit that is being followed in its state by this unit, if there is any, otherwise the empty string. + Path dbus.ObjectPath // The unit object path + JobId uint32 // If there is a job queued for the job unit the numeric job id, 0 otherwise + JobType string // The job type as string + JobPath dbus.ObjectPath // The job object path +} + +type storeFunc func(retvalues ...interface{}) error + +func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) { + result := make([][]interface{}, 0) + err := f(&result) + if err != nil { + return nil, err + } + + resultInterface := make([]interface{}, len(result)) + for i := range result { + resultInterface[i] = result[i] + } + + status := make([]UnitStatus, len(result)) + statusInterface := make([]interface{}, len(status)) + for i := range status { + statusInterface[i] = &status[i] + } + + err = dbus.Store(resultInterface, statusInterface...) + if err != nil { + return nil, err + } + + return status, nil +} + +// ListUnits returns an array with all currently loaded units. Note that +// units may be known by multiple names at the same time, and hence there might +// be more unit names loaded than actual units behind them. +// Also note that a unit is only loaded if it is active and/or enabled. +// Units that are both disabled and inactive will thus not be returned. +func (c *Conn) ListUnits() ([]UnitStatus, error) { + return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store) +} + +// ListUnitsFiltered returns an array with units filtered by state. +// It takes a list of units' statuses to filter. +func (c *Conn) ListUnitsFiltered(states []string) ([]UnitStatus, error) { + return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store) +} + +// ListUnitsByPatterns returns an array with units. +// It takes a list of units' statuses and names to filter. +// Note that units may be known by multiple names at the same time, +// and hence there might be more unit names loaded than actual units behind them. +func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) { + return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store) +} + +// ListUnitsByNames returns an array with units. It takes a list of units' +// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns +// method, this method returns statuses even for inactive or non-existing +// units. Input array should contain exact unit names, but not patterns. +// Note: Requires systemd v230 or higher +func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) { + return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store) +} + +type UnitFile struct { + Path string + Type string +} + +func (c *Conn) listUnitFilesInternal(f storeFunc) ([]UnitFile, error) { + result := make([][]interface{}, 0) + err := f(&result) + if err != nil { + return nil, err + } + + resultInterface := make([]interface{}, len(result)) + for i := range result { + resultInterface[i] = result[i] + } + + files := make([]UnitFile, len(result)) + fileInterface := make([]interface{}, len(files)) + for i := range files { + fileInterface[i] = &files[i] + } + + err = dbus.Store(resultInterface, fileInterface...) + if err != nil { + return nil, err + } + + return files, nil +} + +// ListUnitFiles returns an array of all available units on disk. +func (c *Conn) ListUnitFiles() ([]UnitFile, error) { + return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store) +} + +// ListUnitFilesByPatterns returns an array of all available units on disk matched the patterns. +func (c *Conn) ListUnitFilesByPatterns(states []string, patterns []string) ([]UnitFile, error) { + return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store) +} + +type LinkUnitFileChange EnableUnitFileChange + +// LinkUnitFiles() links unit files (that are located outside of the +// usual unit search paths) into the unit search path. +// +// It takes a list of absolute paths to unit files to link and two +// booleans. The first boolean controls whether the unit shall be +// enabled for runtime only (true, /run), or persistently (false, +// /etc). +// The second controls whether symlinks pointing to other units shall +// be replaced if necessary. +// +// This call returns a list of the changes made. The list consists of +// structures with three strings: the type of the change (one of symlink +// or unlink), the file name of the symlink and the destination of the +// symlink. +func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) { + result := make([][]interface{}, 0) + err := c.sysobj.Call("org.freedesktop.systemd1.Manager.LinkUnitFiles", 0, files, runtime, force).Store(&result) + if err != nil { + return nil, err + } + + resultInterface := make([]interface{}, len(result)) + for i := range result { + resultInterface[i] = result[i] + } + + changes := make([]LinkUnitFileChange, len(result)) + changesInterface := make([]interface{}, len(changes)) + for i := range changes { + changesInterface[i] = &changes[i] + } + + err = dbus.Store(resultInterface, changesInterface...) + if err != nil { + return nil, err + } + + return changes, nil +} + +// EnableUnitFiles() may be used to enable one or more units in the system (by +// creating symlinks to them in /etc or /run). +// +// It takes a list of unit files to enable (either just file names or full +// absolute paths if the unit files are residing outside the usual unit +// search paths), and two booleans: the first controls whether the unit shall +// be enabled for runtime only (true, /run), or persistently (false, /etc). +// The second one controls whether symlinks pointing to other units shall +// be replaced if necessary. +// +// This call returns one boolean and an array with the changes made. The +// boolean signals whether the unit files contained any enablement +// information (i.e. an [Install]) section. The changes list consists of +// structures with three strings: the type of the change (one of symlink +// or unlink), the file name of the symlink and the destination of the +// symlink. +func (c *Conn) EnableUnitFiles(files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) { + var carries_install_info bool + + result := make([][]interface{}, 0) + err := c.sysobj.Call("org.freedesktop.systemd1.Manager.EnableUnitFiles", 0, files, runtime, force).Store(&carries_install_info, &result) + if err != nil { + return false, nil, err + } + + resultInterface := make([]interface{}, len(result)) + for i := range result { + resultInterface[i] = result[i] + } + + changes := make([]EnableUnitFileChange, len(result)) + changesInterface := make([]interface{}, len(changes)) + for i := range changes { + changesInterface[i] = &changes[i] + } + + err = dbus.Store(resultInterface, changesInterface...) + if err != nil { + return false, nil, err + } + + return carries_install_info, changes, nil +} + +type EnableUnitFileChange struct { + Type string // Type of the change (one of symlink or unlink) + Filename string // File name of the symlink + Destination string // Destination of the symlink +} + +// DisableUnitFiles() may be used to disable one or more units in the system (by +// removing symlinks to them from /etc or /run). +// +// It takes a list of unit files to disable (either just file names or full +// absolute paths if the unit files are residing outside the usual unit +// search paths), and one boolean: whether the unit was enabled for runtime +// only (true, /run), or persistently (false, /etc). +// +// This call returns an array with the changes made. The changes list +// consists of structures with three strings: the type of the change (one of +// symlink or unlink), the file name of the symlink and the destination of the +// symlink. +func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFileChange, error) { + result := make([][]interface{}, 0) + err := c.sysobj.Call("org.freedesktop.systemd1.Manager.DisableUnitFiles", 0, files, runtime).Store(&result) + if err != nil { + return nil, err + } + + resultInterface := make([]interface{}, len(result)) + for i := range result { + resultInterface[i] = result[i] + } + + changes := make([]DisableUnitFileChange, len(result)) + changesInterface := make([]interface{}, len(changes)) + for i := range changes { + changesInterface[i] = &changes[i] + } + + err = dbus.Store(resultInterface, changesInterface...) + if err != nil { + return nil, err + } + + return changes, nil +} + +type DisableUnitFileChange struct { + Type string // Type of the change (one of symlink or unlink) + Filename string // File name of the symlink + Destination string // Destination of the symlink +} + +// MaskUnitFiles masks one or more units in the system +// +// It takes three arguments: +// * list of units to mask (either just file names or full +// absolute paths if the unit files are residing outside +// the usual unit search paths) +// * runtime to specify whether the unit was enabled for runtime +// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..) +// * force flag +func (c *Conn) MaskUnitFiles(files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) { + result := make([][]interface{}, 0) + err := c.sysobj.Call("org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result) + if err != nil { + return nil, err + } + + resultInterface := make([]interface{}, len(result)) + for i := range result { + resultInterface[i] = result[i] + } + + changes := make([]MaskUnitFileChange, len(result)) + changesInterface := make([]interface{}, len(changes)) + for i := range changes { + changesInterface[i] = &changes[i] + } + + err = dbus.Store(resultInterface, changesInterface...) + if err != nil { + return nil, err + } + + return changes, nil +} + +type MaskUnitFileChange struct { + Type string // Type of the change (one of symlink or unlink) + Filename string // File name of the symlink + Destination string // Destination of the symlink +} + +// UnmaskUnitFiles unmasks one or more units in the system +// +// It takes two arguments: +// * list of unit files to mask (either just file names or full +// absolute paths if the unit files are residing outside +// the usual unit search paths) +// * runtime to specify whether the unit was enabled for runtime +// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..) +func (c *Conn) UnmaskUnitFiles(files []string, runtime bool) ([]UnmaskUnitFileChange, error) { + result := make([][]interface{}, 0) + err := c.sysobj.Call("org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result) + if err != nil { + return nil, err + } + + resultInterface := make([]interface{}, len(result)) + for i := range result { + resultInterface[i] = result[i] + } + + changes := make([]UnmaskUnitFileChange, len(result)) + changesInterface := make([]interface{}, len(changes)) + for i := range changes { + changesInterface[i] = &changes[i] + } + + err = dbus.Store(resultInterface, changesInterface...) + if err != nil { + return nil, err + } + + return changes, nil +} + +type UnmaskUnitFileChange struct { + Type string // Type of the change (one of symlink or unlink) + Filename string // File name of the symlink + Destination string // Destination of the symlink +} + +// Reload instructs systemd to scan for and reload unit files. This is +// equivalent to a 'systemctl daemon-reload'. +func (c *Conn) Reload() error { + return c.sysobj.Call("org.freedesktop.systemd1.Manager.Reload", 0).Store() +} + +func unitPath(name string) dbus.ObjectPath { + return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name)) +} + +// unitName returns the unescaped base element of the supplied escaped path +func unitName(dpath dbus.ObjectPath) string { + return pathBusUnescape(path.Base(string(dpath))) +} diff --git a/vendor/github.com/coreos/go-systemd/dbus/properties.go b/vendor/github.com/coreos/go-systemd/dbus/properties.go new file mode 100644 index 000000000000..6c8189587636 --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/dbus/properties.go @@ -0,0 +1,237 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dbus + +import ( + "github.com/godbus/dbus" +) + +// From the systemd docs: +// +// The properties array of StartTransientUnit() may take many of the settings +// that may also be configured in unit files. Not all parameters are currently +// accepted though, but we plan to cover more properties with future release. +// Currently you may set the Description, Slice and all dependency types of +// units, as well as RemainAfterExit, ExecStart for service units, +// TimeoutStopUSec and PIDs for scope units, and CPUAccounting, CPUShares, +// BlockIOAccounting, BlockIOWeight, BlockIOReadBandwidth, +// BlockIOWriteBandwidth, BlockIODeviceWeight, MemoryAccounting, MemoryLimit, +// DevicePolicy, DeviceAllow for services/scopes/slices. These fields map +// directly to their counterparts in unit files and as normal D-Bus object +// properties. The exception here is the PIDs field of scope units which is +// used for construction of the scope only and specifies the initial PIDs to +// add to the scope object. + +type Property struct { + Name string + Value dbus.Variant +} + +type PropertyCollection struct { + Name string + Properties []Property +} + +type execStart struct { + Path string // the binary path to execute + Args []string // an array with all arguments to pass to the executed command, starting with argument 0 + UncleanIsFailure bool // a boolean whether it should be considered a failure if the process exits uncleanly +} + +// PropExecStart sets the ExecStart service property. The first argument is a +// slice with the binary path to execute followed by the arguments to pass to +// the executed command. See +// http://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart= +func PropExecStart(command []string, uncleanIsFailure bool) Property { + execStarts := []execStart{ + execStart{ + Path: command[0], + Args: command, + UncleanIsFailure: uncleanIsFailure, + }, + } + + return Property{ + Name: "ExecStart", + Value: dbus.MakeVariant(execStarts), + } +} + +// PropRemainAfterExit sets the RemainAfterExit service property. See +// http://www.freedesktop.org/software/systemd/man/systemd.service.html#RemainAfterExit= +func PropRemainAfterExit(b bool) Property { + return Property{ + Name: "RemainAfterExit", + Value: dbus.MakeVariant(b), + } +} + +// PropType sets the Type service property. See +// http://www.freedesktop.org/software/systemd/man/systemd.service.html#Type= +func PropType(t string) Property { + return Property{ + Name: "Type", + Value: dbus.MakeVariant(t), + } +} + +// PropDescription sets the Description unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit#Description= +func PropDescription(desc string) Property { + return Property{ + Name: "Description", + Value: dbus.MakeVariant(desc), + } +} + +func propDependency(name string, units []string) Property { + return Property{ + Name: name, + Value: dbus.MakeVariant(units), + } +} + +// PropRequires sets the Requires unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Requires= +func PropRequires(units ...string) Property { + return propDependency("Requires", units) +} + +// PropRequiresOverridable sets the RequiresOverridable unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#RequiresOverridable= +func PropRequiresOverridable(units ...string) Property { + return propDependency("RequiresOverridable", units) +} + +// PropRequisite sets the Requisite unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Requisite= +func PropRequisite(units ...string) Property { + return propDependency("Requisite", units) +} + +// PropRequisiteOverridable sets the RequisiteOverridable unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#RequisiteOverridable= +func PropRequisiteOverridable(units ...string) Property { + return propDependency("RequisiteOverridable", units) +} + +// PropWants sets the Wants unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Wants= +func PropWants(units ...string) Property { + return propDependency("Wants", units) +} + +// PropBindsTo sets the BindsTo unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#BindsTo= +func PropBindsTo(units ...string) Property { + return propDependency("BindsTo", units) +} + +// PropRequiredBy sets the RequiredBy unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#RequiredBy= +func PropRequiredBy(units ...string) Property { + return propDependency("RequiredBy", units) +} + +// PropRequiredByOverridable sets the RequiredByOverridable unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#RequiredByOverridable= +func PropRequiredByOverridable(units ...string) Property { + return propDependency("RequiredByOverridable", units) +} + +// PropWantedBy sets the WantedBy unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#WantedBy= +func PropWantedBy(units ...string) Property { + return propDependency("WantedBy", units) +} + +// PropBoundBy sets the BoundBy unit property. See +// http://www.freedesktop.org/software/systemd/main/systemd.unit.html#BoundBy= +func PropBoundBy(units ...string) Property { + return propDependency("BoundBy", units) +} + +// PropConflicts sets the Conflicts unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Conflicts= +func PropConflicts(units ...string) Property { + return propDependency("Conflicts", units) +} + +// PropConflictedBy sets the ConflictedBy unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#ConflictedBy= +func PropConflictedBy(units ...string) Property { + return propDependency("ConflictedBy", units) +} + +// PropBefore sets the Before unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Before= +func PropBefore(units ...string) Property { + return propDependency("Before", units) +} + +// PropAfter sets the After unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#After= +func PropAfter(units ...string) Property { + return propDependency("After", units) +} + +// PropOnFailure sets the OnFailure unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#OnFailure= +func PropOnFailure(units ...string) Property { + return propDependency("OnFailure", units) +} + +// PropTriggers sets the Triggers unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Triggers= +func PropTriggers(units ...string) Property { + return propDependency("Triggers", units) +} + +// PropTriggeredBy sets the TriggeredBy unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#TriggeredBy= +func PropTriggeredBy(units ...string) Property { + return propDependency("TriggeredBy", units) +} + +// PropPropagatesReloadTo sets the PropagatesReloadTo unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#PropagatesReloadTo= +func PropPropagatesReloadTo(units ...string) Property { + return propDependency("PropagatesReloadTo", units) +} + +// PropRequiresMountsFor sets the RequiresMountsFor unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.unit.html#RequiresMountsFor= +func PropRequiresMountsFor(units ...string) Property { + return propDependency("RequiresMountsFor", units) +} + +// PropSlice sets the Slice unit property. See +// http://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#Slice= +func PropSlice(slice string) Property { + return Property{ + Name: "Slice", + Value: dbus.MakeVariant(slice), + } +} + +// PropPids sets the PIDs field of scope units used in the initial construction +// of the scope only and specifies the initial PIDs to add to the scope object. +// See https://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/#properties +func PropPids(pids ...uint32) Property { + return Property{ + Name: "PIDs", + Value: dbus.MakeVariant(pids), + } +} diff --git a/vendor/github.com/coreos/go-systemd/dbus/set.go b/vendor/github.com/coreos/go-systemd/dbus/set.go new file mode 100644 index 000000000000..17c5d485657d --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/dbus/set.go @@ -0,0 +1,47 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dbus + +type set struct { + data map[string]bool +} + +func (s *set) Add(value string) { + s.data[value] = true +} + +func (s *set) Remove(value string) { + delete(s.data, value) +} + +func (s *set) Contains(value string) (exists bool) { + _, exists = s.data[value] + return +} + +func (s *set) Length() int { + return len(s.data) +} + +func (s *set) Values() (values []string) { + for val := range s.data { + values = append(values, val) + } + return +} + +func newSet() *set { + return &set{make(map[string]bool)} +} diff --git a/vendor/github.com/coreos/go-systemd/dbus/subscription.go b/vendor/github.com/coreos/go-systemd/dbus/subscription.go new file mode 100644 index 000000000000..f6d7a08a1063 --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/dbus/subscription.go @@ -0,0 +1,333 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dbus + +import ( + "errors" + "log" + "time" + + "github.com/godbus/dbus" +) + +const ( + cleanIgnoreInterval = int64(10 * time.Second) + ignoreInterval = int64(30 * time.Millisecond) +) + +// Subscribe sets up this connection to subscribe to all systemd dbus events. +// This is required before calling SubscribeUnits. When the connection closes +// systemd will automatically stop sending signals so there is no need to +// explicitly call Unsubscribe(). +func (c *Conn) Subscribe() error { + c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, + "type='signal',interface='org.freedesktop.systemd1.Manager',member='UnitNew'") + c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, + "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'") + + return c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store() +} + +// Unsubscribe this connection from systemd dbus events. +func (c *Conn) Unsubscribe() error { + return c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store() +} + +func (c *Conn) dispatch() { + ch := make(chan *dbus.Signal, signalBuffer) + + c.sigconn.Signal(ch) + + go func() { + for { + signal, ok := <-ch + if !ok { + return + } + + if signal.Name == "org.freedesktop.systemd1.Manager.JobRemoved" { + c.jobComplete(signal) + } + + if c.subStateSubscriber.updateCh == nil && + c.propertiesSubscriber.updateCh == nil { + continue + } + + var unitPath dbus.ObjectPath + switch signal.Name { + case "org.freedesktop.systemd1.Manager.JobRemoved": + unitName := signal.Body[2].(string) + c.sysobj.Call("org.freedesktop.systemd1.Manager.GetUnit", 0, unitName).Store(&unitPath) + case "org.freedesktop.systemd1.Manager.UnitNew": + unitPath = signal.Body[1].(dbus.ObjectPath) + case "org.freedesktop.DBus.Properties.PropertiesChanged": + if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" { + unitPath = signal.Path + + if len(signal.Body) >= 2 { + if changed, ok := signal.Body[1].(map[string]dbus.Variant); ok { + c.sendPropertiesUpdate(unitPath, changed) + } + } + } + } + + if unitPath == dbus.ObjectPath("") { + continue + } + + c.sendSubStateUpdate(unitPath) + } + }() +} + +// SubscribeUnits returns two unbuffered channels which will receive all changed units every +// interval. Deleted units are sent as nil. +func (c *Conn) SubscribeUnits(interval time.Duration) (<-chan map[string]*UnitStatus, <-chan error) { + return c.SubscribeUnitsCustom(interval, 0, func(u1, u2 *UnitStatus) bool { return *u1 != *u2 }, nil) +} + +// SubscribeUnitsCustom is like SubscribeUnits but lets you specify the buffer +// size of the channels, the comparison function for detecting changes and a filter +// function for cutting down on the noise that your channel receives. +func (c *Conn) SubscribeUnitsCustom(interval time.Duration, buffer int, isChanged func(*UnitStatus, *UnitStatus) bool, filterUnit func(string) bool) (<-chan map[string]*UnitStatus, <-chan error) { + old := make(map[string]*UnitStatus) + statusChan := make(chan map[string]*UnitStatus, buffer) + errChan := make(chan error, buffer) + + go func() { + for { + timerChan := time.After(interval) + + units, err := c.ListUnits() + if err == nil { + cur := make(map[string]*UnitStatus) + for i := range units { + if filterUnit != nil && filterUnit(units[i].Name) { + continue + } + cur[units[i].Name] = &units[i] + } + + // add all new or changed units + changed := make(map[string]*UnitStatus) + for n, u := range cur { + if oldU, ok := old[n]; !ok || isChanged(oldU, u) { + changed[n] = u + } + delete(old, n) + } + + // add all deleted units + for oldN := range old { + changed[oldN] = nil + } + + old = cur + + if len(changed) != 0 { + statusChan <- changed + } + } else { + errChan <- err + } + + <-timerChan + } + }() + + return statusChan, errChan +} + +type SubStateUpdate struct { + UnitName string + SubState string +} + +// SetSubStateSubscriber writes to updateCh when any unit's substate changes. +// Although this writes to updateCh on every state change, the reported state +// may be more recent than the change that generated it (due to an unavoidable +// race in the systemd dbus interface). That is, this method provides a good +// way to keep a current view of all units' states, but is not guaranteed to +// show every state transition they go through. Furthermore, state changes +// will only be written to the channel with non-blocking writes. If updateCh +// is full, it attempts to write an error to errCh; if errCh is full, the error +// passes silently. +func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) { + if c == nil { + msg := "nil receiver" + select { + case errCh <- errors.New(msg): + default: + log.Printf("full error channel while reporting: %s\n", msg) + } + return + } + + c.subStateSubscriber.Lock() + defer c.subStateSubscriber.Unlock() + c.subStateSubscriber.updateCh = updateCh + c.subStateSubscriber.errCh = errCh +} + +func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) { + c.subStateSubscriber.Lock() + defer c.subStateSubscriber.Unlock() + + if c.subStateSubscriber.updateCh == nil { + return + } + + isIgnored := c.shouldIgnore(unitPath) + defer c.cleanIgnore() + if isIgnored { + return + } + + info, err := c.GetUnitPathProperties(unitPath) + if err != nil { + select { + case c.subStateSubscriber.errCh <- err: + default: + log.Printf("full error channel while reporting: %s\n", err) + } + return + } + defer c.updateIgnore(unitPath, info) + + name, ok := info["Id"].(string) + if !ok { + msg := "failed to cast info.Id" + select { + case c.subStateSubscriber.errCh <- errors.New(msg): + default: + log.Printf("full error channel while reporting: %s\n", err) + } + return + } + substate, ok := info["SubState"].(string) + if !ok { + msg := "failed to cast info.SubState" + select { + case c.subStateSubscriber.errCh <- errors.New(msg): + default: + log.Printf("full error channel while reporting: %s\n", msg) + } + return + } + + update := &SubStateUpdate{name, substate} + select { + case c.subStateSubscriber.updateCh <- update: + default: + msg := "update channel is full" + select { + case c.subStateSubscriber.errCh <- errors.New(msg): + default: + log.Printf("full error channel while reporting: %s\n", msg) + } + return + } +} + +// The ignore functions work around a wart in the systemd dbus interface. +// Requesting the properties of an unloaded unit will cause systemd to send a +// pair of UnitNew/UnitRemoved signals. Because we need to get a unit's +// properties on UnitNew (as that's the only indication of a new unit coming up +// for the first time), we would enter an infinite loop if we did not attempt +// to detect and ignore these spurious signals. The signal themselves are +// indistinguishable from relevant ones, so we (somewhat hackishly) ignore an +// unloaded unit's signals for a short time after requesting its properties. +// This means that we will miss e.g. a transient unit being restarted +// *immediately* upon failure and also a transient unit being started +// immediately after requesting its status (with systemctl status, for example, +// because this causes a UnitNew signal to be sent which then causes us to fetch +// the properties). + +func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool { + t, ok := c.subStateSubscriber.ignore[path] + return ok && t >= time.Now().UnixNano() +} + +func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) { + loadState, ok := info["LoadState"].(string) + if !ok { + return + } + + // unit is unloaded - it will trigger bad systemd dbus behavior + if loadState == "not-found" { + c.subStateSubscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval + } +} + +// without this, ignore would grow unboundedly over time +func (c *Conn) cleanIgnore() { + now := time.Now().UnixNano() + if c.subStateSubscriber.cleanIgnore < now { + c.subStateSubscriber.cleanIgnore = now + cleanIgnoreInterval + + for p, t := range c.subStateSubscriber.ignore { + if t < now { + delete(c.subStateSubscriber.ignore, p) + } + } + } +} + +// PropertiesUpdate holds a map of a unit's changed properties +type PropertiesUpdate struct { + UnitName string + Changed map[string]dbus.Variant +} + +// SetPropertiesSubscriber writes to updateCh when any unit's properties +// change. Every property change reported by systemd will be sent; that is, no +// transitions will be "missed" (as they might be with SetSubStateSubscriber). +// However, state changes will only be written to the channel with non-blocking +// writes. If updateCh is full, it attempts to write an error to errCh; if +// errCh is full, the error passes silently. +func (c *Conn) SetPropertiesSubscriber(updateCh chan<- *PropertiesUpdate, errCh chan<- error) { + c.propertiesSubscriber.Lock() + defer c.propertiesSubscriber.Unlock() + c.propertiesSubscriber.updateCh = updateCh + c.propertiesSubscriber.errCh = errCh +} + +// we don't need to worry about shouldIgnore() here because +// sendPropertiesUpdate doesn't call GetProperties() +func (c *Conn) sendPropertiesUpdate(unitPath dbus.ObjectPath, changedProps map[string]dbus.Variant) { + c.propertiesSubscriber.Lock() + defer c.propertiesSubscriber.Unlock() + + if c.propertiesSubscriber.updateCh == nil { + return + } + + update := &PropertiesUpdate{unitName(unitPath), changedProps} + + select { + case c.propertiesSubscriber.updateCh <- update: + default: + msg := "update channel is full" + select { + case c.propertiesSubscriber.errCh <- errors.New(msg): + default: + log.Printf("full error channel while reporting: %s\n", msg) + } + return + } +} diff --git a/vendor/github.com/coreos/go-systemd/dbus/subscription_set.go b/vendor/github.com/coreos/go-systemd/dbus/subscription_set.go new file mode 100644 index 000000000000..5b408d5847ad --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/dbus/subscription_set.go @@ -0,0 +1,57 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dbus + +import ( + "time" +) + +// SubscriptionSet returns a subscription set which is like conn.Subscribe but +// can filter to only return events for a set of units. +type SubscriptionSet struct { + *set + conn *Conn +} + +func (s *SubscriptionSet) filter(unit string) bool { + return !s.Contains(unit) +} + +// Subscribe starts listening for dbus events for all of the units in the set. +// Returns channels identical to conn.SubscribeUnits. +func (s *SubscriptionSet) Subscribe() (<-chan map[string]*UnitStatus, <-chan error) { + // TODO: Make fully evented by using systemd 209 with properties changed values + return s.conn.SubscribeUnitsCustom(time.Second, 0, + mismatchUnitStatus, + func(unit string) bool { return s.filter(unit) }, + ) +} + +// NewSubscriptionSet returns a new subscription set. +func (conn *Conn) NewSubscriptionSet() *SubscriptionSet { + return &SubscriptionSet{newSet(), conn} +} + +// mismatchUnitStatus returns true if the provided UnitStatus objects +// are not equivalent. false is returned if the objects are equivalent. +// Only the Name, Description and state-related fields are used in +// the comparison. +func mismatchUnitStatus(u1, u2 *UnitStatus) bool { + return u1.Name != u2.Name || + u1.Description != u2.Description || + u1.LoadState != u2.LoadState || + u1.ActiveState != u2.ActiveState || + u1.SubState != u2.SubState +} diff --git a/vendor/github.com/godbus/dbus/CONTRIBUTING.md b/vendor/github.com/godbus/dbus/CONTRIBUTING.md new file mode 100644 index 000000000000..c88f9b2bdd0b --- /dev/null +++ b/vendor/github.com/godbus/dbus/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# How to Contribute + +## Getting Started + +- Fork the repository on GitHub +- Read the [README](README.markdown) for build and test instructions +- Play with the project, submit bugs, submit patches! + +## Contribution Flow + +This is a rough outline of what a contributor's workflow looks like: + +- Create a topic branch from where you want to base your work (usually master). +- Make commits of logical units. +- Make sure your commit messages are in the proper format (see below). +- Push your changes to a topic branch in your fork of the repository. +- Make sure the tests pass, and add any new tests as appropriate. +- Submit a pull request to the original repository. + +Thanks for your contributions! + +### Format of the Commit Message + +We follow a rough convention for commit messages that is designed to answer two +questions: what changed and why. The subject line should feature the what and +the body of the commit should describe the why. + +``` +scripts: add the test-cluster command + +this uses tmux to setup a test cluster that you can easily kill and +start for debugging. + +Fixes #38 +``` + +The format can be described more formally as follows: + +``` +: + + + +