...

Source file src/github.com/coreos/go-systemd/v22/dbus/methods.go

Documentation: github.com/coreos/go-systemd/v22/dbus

     1  // Copyright 2015, 2018 CoreOS, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package dbus
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"fmt"
    21  	"path"
    22  	"strconv"
    23  
    24  	"github.com/godbus/dbus/v5"
    25  )
    26  
    27  // Who can be used to specify which process to kill in the unit via the KillUnitWithTarget API
    28  type Who string
    29  
    30  const (
    31  	// All sends the signal to all processes in the unit
    32  	All Who = "all"
    33  	// Main sends the signal to the main process of the unit
    34  	Main Who = "main"
    35  	// Control sends the signal to the control process of the unit
    36  	Control Who = "control"
    37  )
    38  
    39  func (c *Conn) jobComplete(signal *dbus.Signal) {
    40  	var id uint32
    41  	var job dbus.ObjectPath
    42  	var unit string
    43  	var result string
    44  	dbus.Store(signal.Body, &id, &job, &unit, &result)
    45  	c.jobListener.Lock()
    46  	out, ok := c.jobListener.jobs[job]
    47  	if ok {
    48  		out <- result
    49  		delete(c.jobListener.jobs, job)
    50  	}
    51  	c.jobListener.Unlock()
    52  }
    53  
    54  func (c *Conn) startJob(ctx context.Context, ch chan<- string, job string, args ...interface{}) (int, error) {
    55  	if ch != nil {
    56  		c.jobListener.Lock()
    57  		defer c.jobListener.Unlock()
    58  	}
    59  
    60  	var p dbus.ObjectPath
    61  	err := c.sysobj.CallWithContext(ctx, job, 0, args...).Store(&p)
    62  	if err != nil {
    63  		return 0, err
    64  	}
    65  
    66  	if ch != nil {
    67  		c.jobListener.jobs[p] = ch
    68  	}
    69  
    70  	// ignore error since 0 is fine if conversion fails
    71  	jobID, _ := strconv.Atoi(path.Base(string(p)))
    72  
    73  	return jobID, nil
    74  }
    75  
    76  // Deprecated: use StartUnitContext instead.
    77  func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) {
    78  	return c.StartUnitContext(context.Background(), name, mode, ch)
    79  }
    80  
    81  // StartUnitContext enqueues a start job and depending jobs, if any (unless otherwise
    82  // specified by the mode string).
    83  //
    84  // Takes the unit to activate, plus a mode string. The mode needs to be one of
    85  // replace, fail, isolate, ignore-dependencies, ignore-requirements. If
    86  // "replace" the call will start the unit and its dependencies, possibly
    87  // replacing already queued jobs that conflict with this. If "fail" the call
    88  // will start the unit and its dependencies, but will fail if this would change
    89  // an already queued job. If "isolate" the call will start the unit in question
    90  // and terminate all units that aren't dependencies of it. If
    91  // "ignore-dependencies" it will start a unit but ignore all its dependencies.
    92  // If "ignore-requirements" it will start a unit but only ignore the
    93  // requirement dependencies. It is not recommended to make use of the latter
    94  // two options.
    95  //
    96  // If the provided channel is non-nil, a result string will be sent to it upon
    97  // job completion: one of done, canceled, timeout, failed, dependency, skipped.
    98  // done indicates successful execution of a job. canceled indicates that a job
    99  // has been canceled  before it finished execution. timeout indicates that the
   100  // job timeout was reached. failed indicates that the job failed. dependency
   101  // indicates that a job this job has been depending on failed and the job hence
   102  // has been removed too. skipped indicates that a job was skipped because it
   103  // didn't apply to the units current state.
   104  //
   105  // If no error occurs, the ID of the underlying systemd job will be returned. There
   106  // does exist the possibility for no error to be returned, but for the returned job
   107  // ID to be 0. In this case, the actual underlying ID is not 0 and this datapoint
   108  // should not be considered authoritative.
   109  //
   110  // If an error does occur, it will be returned to the user alongside a job ID of 0.
   111  func (c *Conn) StartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
   112  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode)
   113  }
   114  
   115  // Deprecated: use StopUnitContext instead.
   116  func (c *Conn) StopUnit(name string, mode string, ch chan<- string) (int, error) {
   117  	return c.StopUnitContext(context.Background(), name, mode, ch)
   118  }
   119  
   120  // StopUnitContext is similar to StartUnitContext, but stops the specified unit
   121  // rather than starting it.
   122  func (c *Conn) StopUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
   123  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode)
   124  }
   125  
   126  // Deprecated: use ReloadUnitContext instead.
   127  func (c *Conn) ReloadUnit(name string, mode string, ch chan<- string) (int, error) {
   128  	return c.ReloadUnitContext(context.Background(), name, mode, ch)
   129  }
   130  
   131  // ReloadUnitContext reloads a unit. Reloading is done only if the unit
   132  // is already running, and fails otherwise.
   133  func (c *Conn) ReloadUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
   134  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadUnit", name, mode)
   135  }
   136  
   137  // Deprecated: use RestartUnitContext instead.
   138  func (c *Conn) RestartUnit(name string, mode string, ch chan<- string) (int, error) {
   139  	return c.RestartUnitContext(context.Background(), name, mode, ch)
   140  }
   141  
   142  // RestartUnitContext restarts a service. If a service is restarted that isn't
   143  // running it will be started.
   144  func (c *Conn) RestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
   145  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.RestartUnit", name, mode)
   146  }
   147  
   148  // Deprecated: use TryRestartUnitContext instead.
   149  func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
   150  	return c.TryRestartUnitContext(context.Background(), name, mode, ch)
   151  }
   152  
   153  // TryRestartUnitContext is like RestartUnitContext, except that a service that
   154  // isn't running is not affected by the restart.
   155  func (c *Conn) TryRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
   156  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode)
   157  }
   158  
   159  // Deprecated: use ReloadOrRestartUnitContext instead.
   160  func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) {
   161  	return c.ReloadOrRestartUnitContext(context.Background(), name, mode, ch)
   162  }
   163  
   164  // ReloadOrRestartUnitContext attempts a reload if the unit supports it and use
   165  // a restart otherwise.
   166  func (c *Conn) ReloadOrRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
   167  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
   168  }
   169  
   170  // Deprecated: use ReloadOrTryRestartUnitContext instead.
   171  func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
   172  	return c.ReloadOrTryRestartUnitContext(context.Background(), name, mode, ch)
   173  }
   174  
   175  // ReloadOrTryRestartUnitContext attempts a reload if the unit supports it,
   176  // and use a "Try" flavored restart otherwise.
   177  func (c *Conn) ReloadOrTryRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
   178  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
   179  }
   180  
   181  // Deprecated: use StartTransientUnitContext instead.
   182  func (c *Conn) StartTransientUnit(name string, mode string, properties []Property, ch chan<- string) (int, error) {
   183  	return c.StartTransientUnitContext(context.Background(), name, mode, properties, ch)
   184  }
   185  
   186  // StartTransientUnitContext may be used to create and start a transient unit, which
   187  // will be released as soon as it is not running or referenced anymore or the
   188  // system is rebooted. name is the unit name including suffix, and must be
   189  // unique. mode is the same as in StartUnitContext, properties contains properties
   190  // of the unit.
   191  func (c *Conn) StartTransientUnitContext(ctx context.Context, name string, mode string, properties []Property, ch chan<- string) (int, error) {
   192  	return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
   193  }
   194  
   195  // Deprecated: use KillUnitContext instead.
   196  func (c *Conn) KillUnit(name string, signal int32) {
   197  	c.KillUnitContext(context.Background(), name, signal)
   198  }
   199  
   200  // KillUnitContext takes the unit name and a UNIX signal number to send.
   201  // All of the unit's processes are killed.
   202  func (c *Conn) KillUnitContext(ctx context.Context, name string, signal int32) {
   203  	c.KillUnitWithTarget(ctx, name, All, signal)
   204  }
   205  
   206  // KillUnitWithTarget is like KillUnitContext, but allows you to specify which
   207  // process in the unit to send the signal to.
   208  func (c *Conn) KillUnitWithTarget(ctx context.Context, name string, target Who, signal int32) error {
   209  	return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.KillUnit", 0, name, string(target), signal).Store()
   210  }
   211  
   212  // Deprecated: use ResetFailedUnitContext instead.
   213  func (c *Conn) ResetFailedUnit(name string) error {
   214  	return c.ResetFailedUnitContext(context.Background(), name)
   215  }
   216  
   217  // ResetFailedUnitContext resets the "failed" state of a specific unit.
   218  func (c *Conn) ResetFailedUnitContext(ctx context.Context, name string) error {
   219  	return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
   220  }
   221  
   222  // Deprecated: use SystemStateContext instead.
   223  func (c *Conn) SystemState() (*Property, error) {
   224  	return c.SystemStateContext(context.Background())
   225  }
   226  
   227  // SystemStateContext returns the systemd state. Equivalent to
   228  // systemctl is-system-running.
   229  func (c *Conn) SystemStateContext(ctx context.Context) (*Property, error) {
   230  	var err error
   231  	var prop dbus.Variant
   232  
   233  	obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
   234  	err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  
   239  	return &Property{Name: "SystemState", Value: prop}, nil
   240  }
   241  
   242  // getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface.
   243  func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
   244  	var err error
   245  	var props map[string]dbus.Variant
   246  
   247  	if !path.IsValid() {
   248  		return nil, fmt.Errorf("invalid unit name: %v", path)
   249  	}
   250  
   251  	obj := c.sysconn.Object("org.freedesktop.systemd1", path)
   252  	err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props)
   253  	if err != nil {
   254  		return nil, err
   255  	}
   256  
   257  	out := make(map[string]interface{}, len(props))
   258  	for k, v := range props {
   259  		out[k] = v.Value()
   260  	}
   261  
   262  	return out, nil
   263  }
   264  
   265  // Deprecated: use GetUnitPropertiesContext instead.
   266  func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
   267  	return c.GetUnitPropertiesContext(context.Background(), unit)
   268  }
   269  
   270  // GetUnitPropertiesContext takes the (unescaped) unit name and returns all of
   271  // its dbus object properties.
   272  func (c *Conn) GetUnitPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
   273  	path := unitPath(unit)
   274  	return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
   275  }
   276  
   277  // Deprecated: use GetUnitPathPropertiesContext instead.
   278  func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) {
   279  	return c.GetUnitPathPropertiesContext(context.Background(), path)
   280  }
   281  
   282  // GetUnitPathPropertiesContext takes the (escaped) unit path and returns all
   283  // of its dbus object properties.
   284  func (c *Conn) GetUnitPathPropertiesContext(ctx context.Context, path dbus.ObjectPath) (map[string]interface{}, error) {
   285  	return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
   286  }
   287  
   288  // Deprecated: use GetAllPropertiesContext instead.
   289  func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) {
   290  	return c.GetAllPropertiesContext(context.Background(), unit)
   291  }
   292  
   293  // GetAllPropertiesContext takes the (unescaped) unit name and returns all of
   294  // its dbus object properties.
   295  func (c *Conn) GetAllPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
   296  	path := unitPath(unit)
   297  	return c.getProperties(ctx, path, "")
   298  }
   299  
   300  func (c *Conn) getProperty(ctx context.Context, unit string, dbusInterface string, propertyName string) (*Property, error) {
   301  	var err error
   302  	var prop dbus.Variant
   303  
   304  	path := unitPath(unit)
   305  	if !path.IsValid() {
   306  		return nil, errors.New("invalid unit name: " + unit)
   307  	}
   308  
   309  	obj := c.sysconn.Object("org.freedesktop.systemd1", path)
   310  	err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, dbusInterface, propertyName).Store(&prop)
   311  	if err != nil {
   312  		return nil, err
   313  	}
   314  
   315  	return &Property{Name: propertyName, Value: prop}, nil
   316  }
   317  
   318  // Deprecated: use GetUnitPropertyContext instead.
   319  func (c *Conn) GetUnitProperty(unit string, propertyName string) (*Property, error) {
   320  	return c.GetUnitPropertyContext(context.Background(), unit, propertyName)
   321  }
   322  
   323  // GetUnitPropertyContext takes an (unescaped) unit name, and a property name,
   324  // and returns the property value.
   325  func (c *Conn) GetUnitPropertyContext(ctx context.Context, unit string, propertyName string) (*Property, error) {
   326  	return c.getProperty(ctx, unit, "org.freedesktop.systemd1.Unit", propertyName)
   327  }
   328  
   329  // Deprecated: use GetServicePropertyContext instead.
   330  func (c *Conn) GetServiceProperty(service string, propertyName string) (*Property, error) {
   331  	return c.GetServicePropertyContext(context.Background(), service, propertyName)
   332  }
   333  
   334  // GetServiceProperty returns property for given service name and property name.
   335  func (c *Conn) GetServicePropertyContext(ctx context.Context, service string, propertyName string) (*Property, error) {
   336  	return c.getProperty(ctx, service, "org.freedesktop.systemd1.Service", propertyName)
   337  }
   338  
   339  // Deprecated: use GetUnitTypePropertiesContext instead.
   340  func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
   341  	return c.GetUnitTypePropertiesContext(context.Background(), unit, unitType)
   342  }
   343  
   344  // GetUnitTypePropertiesContext returns the extra properties for a unit, specific to the unit type.
   345  // Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope.
   346  // Returns "dbus.Error: Unknown interface" error if the unitType is not the correct type of the unit.
   347  func (c *Conn) GetUnitTypePropertiesContext(ctx context.Context, unit string, unitType string) (map[string]interface{}, error) {
   348  	path := unitPath(unit)
   349  	return c.getProperties(ctx, path, "org.freedesktop.systemd1."+unitType)
   350  }
   351  
   352  // Deprecated: use SetUnitPropertiesContext instead.
   353  func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Property) error {
   354  	return c.SetUnitPropertiesContext(context.Background(), name, runtime, properties...)
   355  }
   356  
   357  // SetUnitPropertiesContext may be used to modify certain unit properties at runtime.
   358  // Not all properties may be changed at runtime, but many resource management
   359  // settings (primarily those in systemd.cgroup(5)) may. The changes are applied
   360  // instantly, and stored on disk for future boots, unless runtime is true, in which
   361  // case the settings only apply until the next reboot. name is the name of the unit
   362  // to modify. properties are the settings to set, encoded as an array of property
   363  // name and value pairs.
   364  func (c *Conn) SetUnitPropertiesContext(ctx context.Context, name string, runtime bool, properties ...Property) error {
   365  	return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.SetUnitProperties", 0, name, runtime, properties).Store()
   366  }
   367  
   368  // Deprecated: use GetUnitTypePropertyContext instead.
   369  func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) {
   370  	return c.GetUnitTypePropertyContext(context.Background(), unit, unitType, propertyName)
   371  }
   372  
   373  // GetUnitTypePropertyContext takes a property name, a unit name, and a unit type,
   374  // and returns a property value. For valid values of unitType, see GetUnitTypePropertiesContext.
   375  func (c *Conn) GetUnitTypePropertyContext(ctx context.Context, unit string, unitType string, propertyName string) (*Property, error) {
   376  	return c.getProperty(ctx, unit, "org.freedesktop.systemd1."+unitType, propertyName)
   377  }
   378  
   379  type UnitStatus struct {
   380  	Name        string          // The primary unit name as string
   381  	Description string          // The human readable description string
   382  	LoadState   string          // The load state (i.e. whether the unit file has been loaded successfully)
   383  	ActiveState string          // The active state (i.e. whether the unit is currently started or not)
   384  	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)
   385  	Followed    string          // A unit that is being followed in its state by this unit, if there is any, otherwise the empty string.
   386  	Path        dbus.ObjectPath // The unit object path
   387  	JobId       uint32          // If there is a job queued for the job unit the numeric job id, 0 otherwise
   388  	JobType     string          // The job type as string
   389  	JobPath     dbus.ObjectPath // The job object path
   390  }
   391  
   392  type storeFunc func(retvalues ...interface{}) error
   393  
   394  func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
   395  	result := make([][]interface{}, 0)
   396  	err := f(&result)
   397  	if err != nil {
   398  		return nil, err
   399  	}
   400  
   401  	resultInterface := make([]interface{}, len(result))
   402  	for i := range result {
   403  		resultInterface[i] = result[i]
   404  	}
   405  
   406  	status := make([]UnitStatus, len(result))
   407  	statusInterface := make([]interface{}, len(status))
   408  	for i := range status {
   409  		statusInterface[i] = &status[i]
   410  	}
   411  
   412  	err = dbus.Store(resultInterface, statusInterface...)
   413  	if err != nil {
   414  		return nil, err
   415  	}
   416  
   417  	return status, nil
   418  }
   419  
   420  // GetUnitByPID returns the unit object path of the unit a process ID
   421  // belongs to. It takes a UNIX PID and returns the object path. The PID must
   422  // refer to an existing system process
   423  func (c *Conn) GetUnitByPID(ctx context.Context, pid uint32) (dbus.ObjectPath, error) {
   424  	var result dbus.ObjectPath
   425  
   426  	err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.GetUnitByPID", 0, pid).Store(&result)
   427  
   428  	return result, err
   429  }
   430  
   431  // GetUnitNameByPID returns the name of the unit a process ID belongs to. It
   432  // takes a UNIX PID and returns the object path. The PID must refer to an
   433  // existing system process
   434  func (c *Conn) GetUnitNameByPID(ctx context.Context, pid uint32) (string, error) {
   435  	path, err := c.GetUnitByPID(ctx, pid)
   436  	if err != nil {
   437  		return "", err
   438  	}
   439  
   440  	return unitName(path), nil
   441  }
   442  
   443  // Deprecated: use ListUnitsContext instead.
   444  func (c *Conn) ListUnits() ([]UnitStatus, error) {
   445  	return c.ListUnitsContext(context.Background())
   446  }
   447  
   448  // ListUnitsContext returns an array with all currently loaded units. Note that
   449  // units may be known by multiple names at the same time, and hence there might
   450  // be more unit names loaded than actual units behind them.
   451  // Also note that a unit is only loaded if it is active and/or enabled.
   452  // Units that are both disabled and inactive will thus not be returned.
   453  func (c *Conn) ListUnitsContext(ctx context.Context) ([]UnitStatus, error) {
   454  	return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
   455  }
   456  
   457  // Deprecated: use ListUnitsFilteredContext instead.
   458  func (c *Conn) ListUnitsFiltered(states []string) ([]UnitStatus, error) {
   459  	return c.ListUnitsFilteredContext(context.Background(), states)
   460  }
   461  
   462  // ListUnitsFilteredContext returns an array with units filtered by state.
   463  // It takes a list of units' statuses to filter.
   464  func (c *Conn) ListUnitsFilteredContext(ctx context.Context, states []string) ([]UnitStatus, error) {
   465  	return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store)
   466  }
   467  
   468  // Deprecated: use ListUnitsByPatternsContext instead.
   469  func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) {
   470  	return c.ListUnitsByPatternsContext(context.Background(), states, patterns)
   471  }
   472  
   473  // ListUnitsByPatternsContext returns an array with units.
   474  // It takes a list of units' statuses and names to filter.
   475  // Note that units may be known by multiple names at the same time,
   476  // and hence there might be more unit names loaded than actual units behind them.
   477  func (c *Conn) ListUnitsByPatternsContext(ctx context.Context, states []string, patterns []string) ([]UnitStatus, error) {
   478  	return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store)
   479  }
   480  
   481  // Deprecated: use ListUnitsByNamesContext instead.
   482  func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
   483  	return c.ListUnitsByNamesContext(context.Background(), units)
   484  }
   485  
   486  // ListUnitsByNamesContext returns an array with units. It takes a list of units'
   487  // names and returns an UnitStatus array. Comparing to ListUnitsByPatternsContext
   488  // method, this method returns statuses even for inactive or non-existing
   489  // units. Input array should contain exact unit names, but not patterns.
   490  //
   491  // Requires systemd v230 or higher.
   492  func (c *Conn) ListUnitsByNamesContext(ctx context.Context, units []string) ([]UnitStatus, error) {
   493  	return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
   494  }
   495  
   496  type UnitFile struct {
   497  	Path string
   498  	Type string
   499  }
   500  
   501  func (c *Conn) listUnitFilesInternal(f storeFunc) ([]UnitFile, error) {
   502  	result := make([][]interface{}, 0)
   503  	err := f(&result)
   504  	if err != nil {
   505  		return nil, err
   506  	}
   507  
   508  	resultInterface := make([]interface{}, len(result))
   509  	for i := range result {
   510  		resultInterface[i] = result[i]
   511  	}
   512  
   513  	files := make([]UnitFile, len(result))
   514  	fileInterface := make([]interface{}, len(files))
   515  	for i := range files {
   516  		fileInterface[i] = &files[i]
   517  	}
   518  
   519  	err = dbus.Store(resultInterface, fileInterface...)
   520  	if err != nil {
   521  		return nil, err
   522  	}
   523  
   524  	return files, nil
   525  }
   526  
   527  // Deprecated: use ListUnitFilesContext instead.
   528  func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
   529  	return c.ListUnitFilesContext(context.Background())
   530  }
   531  
   532  // ListUnitFiles returns an array of all available units on disk.
   533  func (c *Conn) ListUnitFilesContext(ctx context.Context) ([]UnitFile, error) {
   534  	return c.listUnitFilesInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store)
   535  }
   536  
   537  // Deprecated: use ListUnitFilesByPatternsContext instead.
   538  func (c *Conn) ListUnitFilesByPatterns(states []string, patterns []string) ([]UnitFile, error) {
   539  	return c.ListUnitFilesByPatternsContext(context.Background(), states, patterns)
   540  }
   541  
   542  // ListUnitFilesByPatternsContext returns an array of all available units on disk matched the patterns.
   543  func (c *Conn) ListUnitFilesByPatternsContext(ctx context.Context, states []string, patterns []string) ([]UnitFile, error) {
   544  	return c.listUnitFilesInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store)
   545  }
   546  
   547  type LinkUnitFileChange EnableUnitFileChange
   548  
   549  // Deprecated: use LinkUnitFilesContext instead.
   550  func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
   551  	return c.LinkUnitFilesContext(context.Background(), files, runtime, force)
   552  }
   553  
   554  // LinkUnitFilesContext links unit files (that are located outside of the
   555  // usual unit search paths) into the unit search path.
   556  //
   557  // It takes a list of absolute paths to unit files to link and two
   558  // booleans.
   559  //
   560  // The first boolean controls whether the unit shall be
   561  // enabled for runtime only (true, /run), or persistently (false,
   562  // /etc).
   563  //
   564  // The second controls whether symlinks pointing to other units shall
   565  // be replaced if necessary.
   566  //
   567  // This call returns a list of the changes made. The list consists of
   568  // structures with three strings: the type of the change (one of symlink
   569  // or unlink), the file name of the symlink and the destination of the
   570  // symlink.
   571  func (c *Conn) LinkUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
   572  	result := make([][]interface{}, 0)
   573  	err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.LinkUnitFiles", 0, files, runtime, force).Store(&result)
   574  	if err != nil {
   575  		return nil, err
   576  	}
   577  
   578  	resultInterface := make([]interface{}, len(result))
   579  	for i := range result {
   580  		resultInterface[i] = result[i]
   581  	}
   582  
   583  	changes := make([]LinkUnitFileChange, len(result))
   584  	changesInterface := make([]interface{}, len(changes))
   585  	for i := range changes {
   586  		changesInterface[i] = &changes[i]
   587  	}
   588  
   589  	err = dbus.Store(resultInterface, changesInterface...)
   590  	if err != nil {
   591  		return nil, err
   592  	}
   593  
   594  	return changes, nil
   595  }
   596  
   597  // Deprecated: use EnableUnitFilesContext instead.
   598  func (c *Conn) EnableUnitFiles(files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
   599  	return c.EnableUnitFilesContext(context.Background(), files, runtime, force)
   600  }
   601  
   602  // EnableUnitFilesContext may be used to enable one or more units in the system
   603  // (by creating symlinks to them in /etc or /run).
   604  //
   605  // It takes a list of unit files to enable (either just file names or full
   606  // absolute paths if the unit files are residing outside the usual unit
   607  // search paths), and two booleans: the first controls whether the unit shall
   608  // be enabled for runtime only (true, /run), or persistently (false, /etc).
   609  // The second one controls whether symlinks pointing to other units shall
   610  // be replaced if necessary.
   611  //
   612  // This call returns one boolean and an array with the changes made. The
   613  // boolean signals whether the unit files contained any enablement
   614  // information (i.e. an [Install]) section. The changes list consists of
   615  // structures with three strings: the type of the change (one of symlink
   616  // or unlink), the file name of the symlink and the destination of the
   617  // symlink.
   618  func (c *Conn) EnableUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
   619  	var carries_install_info bool
   620  
   621  	result := make([][]interface{}, 0)
   622  	err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.EnableUnitFiles", 0, files, runtime, force).Store(&carries_install_info, &result)
   623  	if err != nil {
   624  		return false, nil, err
   625  	}
   626  
   627  	resultInterface := make([]interface{}, len(result))
   628  	for i := range result {
   629  		resultInterface[i] = result[i]
   630  	}
   631  
   632  	changes := make([]EnableUnitFileChange, len(result))
   633  	changesInterface := make([]interface{}, len(changes))
   634  	for i := range changes {
   635  		changesInterface[i] = &changes[i]
   636  	}
   637  
   638  	err = dbus.Store(resultInterface, changesInterface...)
   639  	if err != nil {
   640  		return false, nil, err
   641  	}
   642  
   643  	return carries_install_info, changes, nil
   644  }
   645  
   646  type EnableUnitFileChange struct {
   647  	Type        string // Type of the change (one of symlink or unlink)
   648  	Filename    string // File name of the symlink
   649  	Destination string // Destination of the symlink
   650  }
   651  
   652  // Deprecated: use DisableUnitFilesContext instead.
   653  func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFileChange, error) {
   654  	return c.DisableUnitFilesContext(context.Background(), files, runtime)
   655  }
   656  
   657  // DisableUnitFilesContext may be used to disable one or more units in the
   658  // system (by removing symlinks to them from /etc or /run).
   659  //
   660  // It takes a list of unit files to disable (either just file names or full
   661  // absolute paths if the unit files are residing outside the usual unit
   662  // search paths), and one boolean: whether the unit was enabled for runtime
   663  // only (true, /run), or persistently (false, /etc).
   664  //
   665  // This call returns an array with the changes made. The changes list
   666  // consists of structures with three strings: the type of the change (one of
   667  // symlink or unlink), the file name of the symlink and the destination of the
   668  // symlink.
   669  func (c *Conn) DisableUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]DisableUnitFileChange, error) {
   670  	result := make([][]interface{}, 0)
   671  	err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.DisableUnitFiles", 0, files, runtime).Store(&result)
   672  	if err != nil {
   673  		return nil, err
   674  	}
   675  
   676  	resultInterface := make([]interface{}, len(result))
   677  	for i := range result {
   678  		resultInterface[i] = result[i]
   679  	}
   680  
   681  	changes := make([]DisableUnitFileChange, len(result))
   682  	changesInterface := make([]interface{}, len(changes))
   683  	for i := range changes {
   684  		changesInterface[i] = &changes[i]
   685  	}
   686  
   687  	err = dbus.Store(resultInterface, changesInterface...)
   688  	if err != nil {
   689  		return nil, err
   690  	}
   691  
   692  	return changes, nil
   693  }
   694  
   695  type DisableUnitFileChange struct {
   696  	Type        string // Type of the change (one of symlink or unlink)
   697  	Filename    string // File name of the symlink
   698  	Destination string // Destination of the symlink
   699  }
   700  
   701  // Deprecated: use MaskUnitFilesContext instead.
   702  func (c *Conn) MaskUnitFiles(files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
   703  	return c.MaskUnitFilesContext(context.Background(), files, runtime, force)
   704  }
   705  
   706  // MaskUnitFilesContext masks one or more units in the system.
   707  //
   708  // The files argument contains a  list of units to mask (either just file names
   709  // or full absolute paths if the unit files are residing outside the usual unit
   710  // search paths).
   711  //
   712  // The runtime argument is used to specify whether the unit was enabled for
   713  // runtime only (true, /run/systemd/..), or persistently (false,
   714  // /etc/systemd/..).
   715  func (c *Conn) MaskUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
   716  	result := make([][]interface{}, 0)
   717  	err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result)
   718  	if err != nil {
   719  		return nil, err
   720  	}
   721  
   722  	resultInterface := make([]interface{}, len(result))
   723  	for i := range result {
   724  		resultInterface[i] = result[i]
   725  	}
   726  
   727  	changes := make([]MaskUnitFileChange, len(result))
   728  	changesInterface := make([]interface{}, len(changes))
   729  	for i := range changes {
   730  		changesInterface[i] = &changes[i]
   731  	}
   732  
   733  	err = dbus.Store(resultInterface, changesInterface...)
   734  	if err != nil {
   735  		return nil, err
   736  	}
   737  
   738  	return changes, nil
   739  }
   740  
   741  type MaskUnitFileChange struct {
   742  	Type        string // Type of the change (one of symlink or unlink)
   743  	Filename    string // File name of the symlink
   744  	Destination string // Destination of the symlink
   745  }
   746  
   747  // Deprecated: use UnmaskUnitFilesContext instead.
   748  func (c *Conn) UnmaskUnitFiles(files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
   749  	return c.UnmaskUnitFilesContext(context.Background(), files, runtime)
   750  }
   751  
   752  // UnmaskUnitFilesContext unmasks one or more units in the system.
   753  //
   754  // It takes the list of unit files to mask (either just file names or full
   755  // absolute paths if the unit files are residing outside the usual unit search
   756  // paths), and a boolean runtime flag to specify whether the unit was enabled
   757  // for runtime only (true, /run/systemd/..), or persistently (false,
   758  // /etc/systemd/..).
   759  func (c *Conn) UnmaskUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
   760  	result := make([][]interface{}, 0)
   761  	err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result)
   762  	if err != nil {
   763  		return nil, err
   764  	}
   765  
   766  	resultInterface := make([]interface{}, len(result))
   767  	for i := range result {
   768  		resultInterface[i] = result[i]
   769  	}
   770  
   771  	changes := make([]UnmaskUnitFileChange, len(result))
   772  	changesInterface := make([]interface{}, len(changes))
   773  	for i := range changes {
   774  		changesInterface[i] = &changes[i]
   775  	}
   776  
   777  	err = dbus.Store(resultInterface, changesInterface...)
   778  	if err != nil {
   779  		return nil, err
   780  	}
   781  
   782  	return changes, nil
   783  }
   784  
   785  type UnmaskUnitFileChange struct {
   786  	Type        string // Type of the change (one of symlink or unlink)
   787  	Filename    string // File name of the symlink
   788  	Destination string // Destination of the symlink
   789  }
   790  
   791  // Deprecated: use ReloadContext instead.
   792  func (c *Conn) Reload() error {
   793  	return c.ReloadContext(context.Background())
   794  }
   795  
   796  // ReloadContext instructs systemd to scan for and reload unit files. This is
   797  // an equivalent to systemctl daemon-reload.
   798  func (c *Conn) ReloadContext(ctx context.Context) error {
   799  	return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.Reload", 0).Store()
   800  }
   801  
   802  func unitPath(name string) dbus.ObjectPath {
   803  	return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
   804  }
   805  
   806  // unitName returns the unescaped base element of the supplied escaped path.
   807  func unitName(dpath dbus.ObjectPath) string {
   808  	return pathBusUnescape(path.Base(string(dpath)))
   809  }
   810  
   811  // JobStatus holds a currently queued job definition.
   812  type JobStatus struct {
   813  	Id       uint32          // The numeric job id
   814  	Unit     string          // The primary unit name for this job
   815  	JobType  string          // The job type as string
   816  	Status   string          // The job state as string
   817  	JobPath  dbus.ObjectPath // The job object path
   818  	UnitPath dbus.ObjectPath // The unit object path
   819  }
   820  
   821  // Deprecated: use ListJobsContext instead.
   822  func (c *Conn) ListJobs() ([]JobStatus, error) {
   823  	return c.ListJobsContext(context.Background())
   824  }
   825  
   826  // ListJobsContext returns an array with all currently queued jobs.
   827  func (c *Conn) ListJobsContext(ctx context.Context) ([]JobStatus, error) {
   828  	return c.listJobsInternal(ctx)
   829  }
   830  
   831  func (c *Conn) listJobsInternal(ctx context.Context) ([]JobStatus, error) {
   832  	result := make([][]interface{}, 0)
   833  	if err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListJobs", 0).Store(&result); err != nil {
   834  		return nil, err
   835  	}
   836  
   837  	resultInterface := make([]interface{}, len(result))
   838  	for i := range result {
   839  		resultInterface[i] = result[i]
   840  	}
   841  
   842  	status := make([]JobStatus, len(result))
   843  	statusInterface := make([]interface{}, len(status))
   844  	for i := range status {
   845  		statusInterface[i] = &status[i]
   846  	}
   847  
   848  	if err := dbus.Store(resultInterface, statusInterface...); err != nil {
   849  		return nil, err
   850  	}
   851  
   852  	return status, nil
   853  }
   854  
   855  // Freeze the cgroup associated with the unit.
   856  // Note that FreezeUnit and ThawUnit are only supported on systems running with cgroup v2.
   857  func (c *Conn) FreezeUnit(ctx context.Context, unit string) error {
   858  	return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.FreezeUnit", 0, unit).Store()
   859  }
   860  
   861  // Unfreeze the cgroup associated with the unit.
   862  func (c *Conn) ThawUnit(ctx context.Context, unit string) error {
   863  	return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ThawUnit", 0, unit).Store()
   864  }
   865  

View as plain text