Adding option to configure cgroup to start cri-containerd
Signed-off-by: Abhinandan Prativadi <abhi@docker.com>
This commit is contained in:
		
							
								
								
									
										191
									
								
								vendor/github.com/coreos/go-systemd/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/coreos/go-systemd/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
Apache License
 | 
			
		||||
Version 2.0, January 2004
 | 
			
		||||
http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
1. Definitions.
 | 
			
		||||
 | 
			
		||||
"License" shall mean the terms and conditions for use, reproduction, and
 | 
			
		||||
distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
 | 
			
		||||
owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
"Legal Entity" shall mean the union of the acting entity and all other entities
 | 
			
		||||
that control, are controlled by, or are under common control with that entity.
 | 
			
		||||
For the purposes of this definition, "control" means (i) the power, direct or
 | 
			
		||||
indirect, to cause the direction or management of such entity, whether by
 | 
			
		||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
 | 
			
		||||
permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
"Source" form shall mean the preferred form for making modifications, including
 | 
			
		||||
but not limited to software source code, documentation source, and configuration
 | 
			
		||||
files.
 | 
			
		||||
 | 
			
		||||
"Object" form shall mean any form resulting from mechanical transformation or
 | 
			
		||||
translation of a Source form, including but not limited to compiled object code,
 | 
			
		||||
generated documentation, and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
 | 
			
		||||
available under the License, as indicated by a copyright notice that is included
 | 
			
		||||
in or attached to the work (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
 | 
			
		||||
is based on (or derived from) the Work and for which the editorial revisions,
 | 
			
		||||
annotations, elaborations, or other modifications represent, as a whole, an
 | 
			
		||||
original work of authorship. For the purposes of this License, Derivative Works
 | 
			
		||||
shall not include works that remain separable from, or merely link (or bind by
 | 
			
		||||
name) to the interfaces of, the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
"Contribution" shall mean any work of authorship, including the original version
 | 
			
		||||
of the Work and any modifications or additions to that Work or Derivative Works
 | 
			
		||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
 | 
			
		||||
by the copyright owner or by an individual or Legal Entity authorized to submit
 | 
			
		||||
on behalf of the copyright owner. For the purposes of this definition,
 | 
			
		||||
"submitted" means any form of electronic, verbal, or written communication sent
 | 
			
		||||
to the Licensor or its representatives, including but not limited to
 | 
			
		||||
communication on electronic mailing lists, source code control systems, and
 | 
			
		||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
 | 
			
		||||
the purpose of discussing and improving the Work, but excluding communication
 | 
			
		||||
that is conspicuously marked or otherwise designated in writing by the copyright
 | 
			
		||||
owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
 | 
			
		||||
of whom a Contribution has been received by Licensor and subsequently
 | 
			
		||||
incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
2. Grant of Copyright License.
 | 
			
		||||
 | 
			
		||||
Subject to the terms and conditions of this License, each Contributor hereby
 | 
			
		||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
 | 
			
		||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
publicly display, publicly perform, sublicense, and distribute the Work and such
 | 
			
		||||
Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
3. Grant of Patent License.
 | 
			
		||||
 | 
			
		||||
Subject to the terms and conditions of this License, each Contributor hereby
 | 
			
		||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
 | 
			
		||||
irrevocable (except as stated in this section) patent license to make, have
 | 
			
		||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
 | 
			
		||||
such license applies only to those patent claims licensable by such Contributor
 | 
			
		||||
that are necessarily infringed by their Contribution(s) alone or by combination
 | 
			
		||||
of their Contribution(s) with the Work to which such Contribution(s) was
 | 
			
		||||
submitted. If You institute patent litigation against any entity (including a
 | 
			
		||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
 | 
			
		||||
Contribution incorporated within the Work constitutes direct or contributory
 | 
			
		||||
patent infringement, then any patent licenses granted to You under this License
 | 
			
		||||
for that Work shall terminate as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
4. Redistribution.
 | 
			
		||||
 | 
			
		||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
 | 
			
		||||
in any medium, with or without modifications, and in Source or Object form,
 | 
			
		||||
provided that You meet the following conditions:
 | 
			
		||||
 | 
			
		||||
You must give any other recipients of the Work or Derivative Works a copy of
 | 
			
		||||
this License; and
 | 
			
		||||
You must cause any modified files to carry prominent notices stating that You
 | 
			
		||||
changed the files; and
 | 
			
		||||
You must retain, in the Source form of any Derivative Works that You distribute,
 | 
			
		||||
all copyright, patent, trademark, and attribution notices from the Source form
 | 
			
		||||
of the Work, excluding those notices that do not pertain to any part of the
 | 
			
		||||
Derivative Works; and
 | 
			
		||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
 | 
			
		||||
Derivative Works that You distribute must include a readable copy of the
 | 
			
		||||
attribution notices contained within such NOTICE file, excluding those notices
 | 
			
		||||
that do not pertain to any part of the Derivative Works, in at least one of the
 | 
			
		||||
following places: within a NOTICE text file distributed as part of the
 | 
			
		||||
Derivative Works; within the Source form or documentation, if provided along
 | 
			
		||||
with the Derivative Works; or, within a display generated by the Derivative
 | 
			
		||||
Works, if and wherever such third-party notices normally appear. The contents of
 | 
			
		||||
the NOTICE file are for informational purposes only and do not modify the
 | 
			
		||||
License. You may add Your own attribution notices within Derivative Works that
 | 
			
		||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
 | 
			
		||||
provided that such additional attribution notices cannot be construed as
 | 
			
		||||
modifying the License.
 | 
			
		||||
You may add Your own copyright statement to Your modifications and may provide
 | 
			
		||||
additional or different license terms and conditions for use, reproduction, or
 | 
			
		||||
distribution of Your modifications, or for any such Derivative Works as a whole,
 | 
			
		||||
provided Your use, reproduction, and distribution of the Work otherwise complies
 | 
			
		||||
with the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
5. Submission of Contributions.
 | 
			
		||||
 | 
			
		||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
 | 
			
		||||
for inclusion in the Work by You to the Licensor shall be under the terms and
 | 
			
		||||
conditions of this License, without any additional terms or conditions.
 | 
			
		||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
 | 
			
		||||
any separate license agreement you may have executed with Licensor regarding
 | 
			
		||||
such Contributions.
 | 
			
		||||
 | 
			
		||||
6. Trademarks.
 | 
			
		||||
 | 
			
		||||
This License does not grant permission to use the trade names, trademarks,
 | 
			
		||||
service marks, or product names of the Licensor, except as required for
 | 
			
		||||
reasonable and customary use in describing the origin of the Work and
 | 
			
		||||
reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
7. Disclaimer of Warranty.
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, Licensor provides the
 | 
			
		||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
 | 
			
		||||
including, without limitation, any warranties or conditions of TITLE,
 | 
			
		||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
 | 
			
		||||
solely responsible for determining the appropriateness of using or
 | 
			
		||||
redistributing the Work and assume any risks associated with Your exercise of
 | 
			
		||||
permissions under this License.
 | 
			
		||||
 | 
			
		||||
8. Limitation of Liability.
 | 
			
		||||
 | 
			
		||||
In no event and under no legal theory, whether in tort (including negligence),
 | 
			
		||||
contract, or otherwise, unless required by applicable law (such as deliberate
 | 
			
		||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
liable to You for damages, including any direct, indirect, special, incidental,
 | 
			
		||||
or consequential damages of any character arising as a result of this License or
 | 
			
		||||
out of the use or inability to use the Work (including but not limited to
 | 
			
		||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
 | 
			
		||||
any and all other commercial damages or losses), even if such Contributor has
 | 
			
		||||
been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
9. Accepting Warranty or Additional Liability.
 | 
			
		||||
 | 
			
		||||
While redistributing the Work or Derivative Works thereof, You may choose to
 | 
			
		||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
 | 
			
		||||
other liability obligations and/or rights consistent with this License. However,
 | 
			
		||||
in accepting such obligations, You may act only on Your own behalf and on Your
 | 
			
		||||
sole responsibility, not on behalf of any other Contributor, and only if You
 | 
			
		||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
 | 
			
		||||
incurred by, or claims asserted against, such Contributor by reason of your
 | 
			
		||||
accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
APPENDIX: How to apply the Apache License to your work
 | 
			
		||||
 | 
			
		||||
To apply the Apache License to your work, attach the following boilerplate
 | 
			
		||||
notice, with the fields enclosed by brackets "[]" replaced with your own
 | 
			
		||||
identifying information. (Don't include the brackets!) The text should be
 | 
			
		||||
enclosed in the appropriate comment syntax for the file format. We also
 | 
			
		||||
recommend that a file or class name and description of purpose be included on
 | 
			
		||||
the same "printed page" as the copyright notice for easier identification within
 | 
			
		||||
third-party archives.
 | 
			
		||||
 | 
			
		||||
   Copyright [yyyy] [name of copyright owner]
 | 
			
		||||
 | 
			
		||||
   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.
 | 
			
		||||
							
								
								
									
										54
									
								
								vendor/github.com/coreos/go-systemd/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								vendor/github.com/coreos/go-systemd/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
# go-systemd
 | 
			
		||||
 | 
			
		||||
[](https://travis-ci.org/coreos/go-systemd)
 | 
			
		||||
[](http://godoc.org/github.com/coreos/go-systemd)
 | 
			
		||||
 | 
			
		||||
Go bindings to systemd. The project has several packages:
 | 
			
		||||
 | 
			
		||||
- `activation` - for writing and using socket activation from Go
 | 
			
		||||
- `dbus` - for starting/stopping/inspecting running services and units
 | 
			
		||||
- `journal` - for writing to systemd's logging service, journald
 | 
			
		||||
- `sdjournal` - for reading from journald by wrapping its C API
 | 
			
		||||
- `machine1` - for registering machines/containers with systemd
 | 
			
		||||
- `unit` - for (de)serialization and comparison of unit files
 | 
			
		||||
 | 
			
		||||
## Socket Activation
 | 
			
		||||
 | 
			
		||||
An example HTTP server using socket activation can be quickly set up by following this README on a Linux machine running systemd:
 | 
			
		||||
 | 
			
		||||
https://github.com/coreos/go-systemd/tree/master/examples/activation/httpserver
 | 
			
		||||
 | 
			
		||||
## Journal
 | 
			
		||||
 | 
			
		||||
Using the pure-Go `journal` package you can submit journal entries directly to systemd's journal, taking advantage of features like indexed key/value pairs for each log entry.
 | 
			
		||||
The `sdjournal` package provides read access to the journal by wrapping around journald's native C API; consequently it requires cgo and the journal headers to be available.
 | 
			
		||||
 | 
			
		||||
## D-Bus
 | 
			
		||||
 | 
			
		||||
The `dbus` package connects to the [systemd D-Bus API](http://www.freedesktop.org/wiki/Software/systemd/dbus/) and lets you start, stop and introspect systemd units. The API docs are here:
 | 
			
		||||
 | 
			
		||||
http://godoc.org/github.com/coreos/go-systemd/dbus
 | 
			
		||||
 | 
			
		||||
### Debugging
 | 
			
		||||
 | 
			
		||||
Create `/etc/dbus-1/system-local.conf` that looks like this:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
<!DOCTYPE busconfig PUBLIC
 | 
			
		||||
"-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
 | 
			
		||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 | 
			
		||||
<busconfig>
 | 
			
		||||
    <policy user="root">
 | 
			
		||||
        <allow eavesdrop="true"/>
 | 
			
		||||
        <allow eavesdrop="true" send_destination="*"/>
 | 
			
		||||
    </policy>
 | 
			
		||||
</busconfig>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## machined
 | 
			
		||||
 | 
			
		||||
The `machine1` package allows interaction with the [systemd machined D-Bus API](http://www.freedesktop.org/wiki/Software/systemd/machined/).
 | 
			
		||||
 | 
			
		||||
## Units
 | 
			
		||||
 | 
			
		||||
The `unit` package provides various functions for working with [systemd unit files](http://www.freedesktop.org/software/systemd/man/systemd.unit.html).
 | 
			
		||||
							
								
								
									
										213
									
								
								vendor/github.com/coreos/go-systemd/dbus/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								vendor/github.com/coreos/go-systemd/dbus/dbus.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
// 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 (
 | 
			
		||||
	"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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
	}
 | 
			
		||||
	subscriber struct {
 | 
			
		||||
		updateCh chan<- *SubStateUpdate
 | 
			
		||||
		errCh    chan<- error
 | 
			
		||||
		sync.Mutex
 | 
			
		||||
		ignore      map[dbus.ObjectPath]int64
 | 
			
		||||
		cleanIgnore int64
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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() (*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.subscriber.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() (*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() (*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"))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										565
									
								
								vendor/github.com/coreos/go-systemd/dbus/methods.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										565
									
								
								vendor/github.com/coreos/go-systemd/dbus/methods.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,565 @@
 | 
			
		||||
// 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"
 | 
			
		||||
	"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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReloadOrRestart 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReloadOrTryRestart 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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getProperties takes the unit name and returns all of its dbus object properties, for the given dbus interface
 | 
			
		||||
func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	var props map[string]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.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 unit name and returns all of its dbus object properties.
 | 
			
		||||
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
 | 
			
		||||
	return c.getProperties(unit, "org.freedesktop.systemd1.Unit")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
	return c.getProperties(unit, "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.
 | 
			
		||||
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.
 | 
			
		||||
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))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										237
									
								
								vendor/github.com/coreos/go-systemd/dbus/properties.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								vendor/github.com/coreos/go-systemd/dbus/properties.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -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),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								vendor/github.com/coreos/go-systemd/dbus/set.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/coreos/go-systemd/dbus/set.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -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)}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										250
									
								
								vendor/github.com/coreos/go-systemd/dbus/subscription.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								vendor/github.com/coreos/go-systemd/dbus/subscription.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,250 @@
 | 
			
		||||
// 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"
 | 
			
		||||
	"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'")
 | 
			
		||||
 | 
			
		||||
	err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unsubscribe this connection from systemd dbus events.
 | 
			
		||||
func (c *Conn) Unsubscribe() error {
 | 
			
		||||
	err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.subscriber.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 unitPath == dbus.ObjectPath("") {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			c.sendSubStateUpdate(unitPath)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	c.subscriber.Lock()
 | 
			
		||||
	defer c.subscriber.Unlock()
 | 
			
		||||
	c.subscriber.updateCh = updateCh
 | 
			
		||||
	c.subscriber.errCh = errCh
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
 | 
			
		||||
	c.subscriber.Lock()
 | 
			
		||||
	defer c.subscriber.Unlock()
 | 
			
		||||
 | 
			
		||||
	if c.shouldIgnore(path) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info, err := c.GetUnitProperties(string(path))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		select {
 | 
			
		||||
		case c.subscriber.errCh <- err:
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name := info["Id"].(string)
 | 
			
		||||
	substate := info["SubState"].(string)
 | 
			
		||||
 | 
			
		||||
	update := &SubStateUpdate{name, substate}
 | 
			
		||||
	select {
 | 
			
		||||
	case c.subscriber.updateCh <- update:
 | 
			
		||||
	default:
 | 
			
		||||
		select {
 | 
			
		||||
		case c.subscriber.errCh <- errors.New("update channel full!"):
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.updateIgnore(path, info)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.subscriber.ignore[path]
 | 
			
		||||
	return ok && t >= time.Now().UnixNano()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
 | 
			
		||||
	c.cleanIgnore()
 | 
			
		||||
 | 
			
		||||
	// unit is unloaded - it will trigger bad systemd dbus behavior
 | 
			
		||||
	if info["LoadState"].(string) == "not-found" {
 | 
			
		||||
		c.subscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// without this, ignore would grow unboundedly over time
 | 
			
		||||
func (c *Conn) cleanIgnore() {
 | 
			
		||||
	now := time.Now().UnixNano()
 | 
			
		||||
	if c.subscriber.cleanIgnore < now {
 | 
			
		||||
		c.subscriber.cleanIgnore = now + cleanIgnoreInterval
 | 
			
		||||
 | 
			
		||||
		for p, t := range c.subscriber.ignore {
 | 
			
		||||
			if t < now {
 | 
			
		||||
				delete(c.subscriber.ignore, p)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								vendor/github.com/coreos/go-systemd/dbus/subscription_set.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								vendor/github.com/coreos/go-systemd/dbus/subscription_set.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user