networkmanager-dbus 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Guardfile +5 -1
- data/README.md +20 -2
- data/Rakefile +13 -1
- data/TODO.md +3 -3
- data/examples/change_ip.rb +17 -0
- data/examples/connectivity.rb +1 -1
- data/lib/dbus_interface.rb +14 -5
- data/lib/dbus_interface/class.rb +28 -4
- data/lib/dbus_interface/connection.rb +58 -0
- data/lib/dbus_interface/object.rb +15 -7
- data/lib/network_manager.rb +3 -2
- data/lib/network_manager/dbus.rb +2 -0
- data/lib/network_manager/dbus/device.rb +9 -7
- data/lib/network_manager/dbus/root.rb +8 -4
- data/lib/network_manager/dbus/settings.rb +18 -5
- data/lib/network_manager/dbus/settings_connection.rb +86 -0
- data/lib/network_manager/ip4_config.rb +33 -0
- data/lib/network_manager/version.rb +1 -1
- data/lib/networkmanager-dbus.rb +1 -1
- data/networkmanager-dbus.gemspec +4 -0
- data/script/console +7 -0
- data/script/spec_server +1 -0
- data/spec/fixtures/active_connections.yml +10 -0
- data/spec/fixtures/devices.yml +18 -37
- data/spec/fixtures/dhcp4_configs.yml +17 -0
- data/spec/fixtures/ip4_configs.yml +7 -0
- data/spec/fixtures/settings.yml +4 -14
- data/spec/fixtures/settings_connections.yml +10 -0
- data/spec/lib/dbus_interface/class_spec.rb +31 -0
- data/spec/lib/dbus_interface/object_spec.rb +32 -0
- data/spec/{network_manager → lib/network_manager}/dbus/active_connection_spec.rb +6 -6
- data/spec/lib/network_manager/dbus/device_spec.rb +58 -0
- data/spec/lib/network_manager/dbus/dhcp4_config_spec.rb +19 -0
- data/spec/lib/network_manager/dbus/ethernet_device_spec.rb +14 -0
- data/spec/lib/network_manager/dbus/ip4_config_spec.rb +19 -0
- data/spec/lib/network_manager/dbus/root_spec.rb +38 -0
- data/spec/lib/network_manager/dbus/settings_connection_spec.rb +69 -0
- data/spec/lib/network_manager/dbus/settings_spec.rb +53 -0
- data/spec/lib/network_manager/ip4_config_spec.rb +27 -0
- data/spec/{network_manager_spec.rb → lib/network_manager_spec.rb} +2 -0
- data/spec/mocks/dbus/ethernet_device_mock.rb +5 -0
- data/spec/mocks/dbus/root_mock.rb +14 -0
- data/spec/mocks/dbus/settings_connection_mock.rb +21 -0
- data/spec/mocks/dbus/settings_mock.rb +9 -0
- data/spec/mocks/dbus_mock.rb +33 -0
- data/spec/mocks/init.rb +18 -0
- data/spec/mocks/system_bus_mock.rb +5 -0
- data/spec/mocks/system_bus_service_mock.rb +9 -0
- data/spec/spec_helper.rb +22 -3
- data/spec/support/fixture_helper.rb +21 -4
- metadata +96 -28
- data/lib/network_manager/ip4_helper.rb +0 -14
- data/spec/network_manager/dbus/device_spec.rb +0 -36
- data/spec/network_manager/dbus/dhcp4_config_spec.rb +0 -14
- data/spec/network_manager/dbus/ethernet_device_spec.rb +0 -21
- data/spec/network_manager/dbus/ip4_config_spec.rb +0 -14
- data/spec/network_manager/dbus/root_spec.rb +0 -22
- data/spec/network_manager/dbus/settings_connection_spec.rb +0 -13
- data/spec/network_manager/dbus/settings_spec.rb +0 -30
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,18 @@
|
|
1
|
+
THIS IS ALPHA STUFF :)
|
2
|
+
|
3
|
+
see [TODOs](TODO.md)
|
4
|
+
|
5
|
+
[![Travis-CI Build Status](https://secure.travis-ci.org/dpree/networkmanager-dbus.png)](https://secure.travis-ci.org/dpree/networkmanager-dbus)
|
6
|
+
|
1
7
|
# NetworkManager-Ruby
|
2
8
|
|
3
9
|
This library provides a Ruby API to NetworkManager using its DBus Interface.
|
4
10
|
|
11
|
+
Written using the NetworkManager DBus API Documentation v0.9
|
12
|
+
|
13
|
+
* [General API](http://projects.gnome.org/NetworkManager/developers/api/09/spec.html)
|
14
|
+
* [Details](http://projects.gnome.org/NetworkManager/developers/api/09/ref-settings.html)
|
15
|
+
|
5
16
|
## Installation
|
6
17
|
|
7
18
|
Please make sure that you have `dbus` and `networkmanager` installed on the machine
|
@@ -22,7 +33,7 @@ please have a look at the `examples` folder and the `specs`.
|
|
22
33
|
|
23
34
|
Development currently happens from my OSX machine where no dbus/networkmanager
|
24
35
|
is running. Therefore, i hacked some scripts together to be able to run rspec
|
25
|
-
over the wire
|
36
|
+
over the wire.
|
26
37
|
|
27
38
|
On the remote-machine (linux, dbus, networkmanager)
|
28
39
|
|
@@ -32,6 +43,13 @@ On the local-machine (osx)
|
|
32
43
|
|
33
44
|
`guard`
|
34
45
|
|
46
|
+
# Thanks
|
47
|
+
|
48
|
+
to the guys from IRC channel #nm at irc.freenode.net
|
49
|
+
|
50
|
+
* dbcw
|
51
|
+
* jklimes
|
52
|
+
|
35
53
|
# License
|
36
54
|
|
37
|
-
|
55
|
+
Copyright 2011 Jens Bissinger. All rights reserved. [MIT-LICENSE](MIT-LICENSE)
|
data/Rakefile
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.require :development
|
5
|
+
|
3
6
|
def pump_dumps(dumps)
|
4
7
|
dumps.each do |obj|
|
5
8
|
case obj['action']
|
@@ -40,7 +43,7 @@ namespace :spec do
|
|
40
43
|
desc 'run specs on a remote server (script/spec_server)'
|
41
44
|
task :remote do
|
42
45
|
begin
|
43
|
-
client = MarilynRPC::NativeClient.connect_tcp('192.168.56.101', 8483)
|
46
|
+
client = ::MarilynRPC::NativeClient.connect_tcp('192.168.56.101', 8483)
|
44
47
|
runner = client.for :rspec
|
45
48
|
json = runner.run
|
46
49
|
begin
|
@@ -63,3 +66,12 @@ namespace :spec do
|
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
69
|
+
require 'rspec/core/rake_task'
|
70
|
+
desc 'Default: run specs.'
|
71
|
+
desc "Run specs"
|
72
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
73
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
74
|
+
# Put spec opts in a file named .rspec in root
|
75
|
+
end
|
76
|
+
task :default => :spec
|
77
|
+
|
data/TODO.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# TODOs
|
2
2
|
|
3
3
|
* more specs :)
|
4
|
-
*
|
5
|
-
*
|
6
|
-
*
|
4
|
+
* cleanup specs
|
5
|
+
* better mocking
|
6
|
+
* refactor integration specs
|
7
7
|
* add missing interfaces
|
8
8
|
* different device types
|
9
9
|
* vpn
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../lib/network_manager')
|
2
|
+
|
3
|
+
# the first setting (hopefully a eth0 default foo)
|
4
|
+
con = NetworkManager::DBus::Settings.connections.first
|
5
|
+
|
6
|
+
# new ip4 config
|
7
|
+
# ip + netmask + gateway
|
8
|
+
ip4 = NetworkManager::Ip4Config.from_dot_notation '192.168.10.100', '255.255.255.0', '192.168.10.1'
|
9
|
+
|
10
|
+
# change the settings obj
|
11
|
+
con.ip4_manual = ip4
|
12
|
+
|
13
|
+
# take minor important device no.2 :)
|
14
|
+
dev = NetworkManager.devices[1]
|
15
|
+
|
16
|
+
# apply the settings obj to the dev
|
17
|
+
NetworkManager::DBus::Root.activate_connection con, dev
|
data/examples/connectivity.rb
CHANGED
@@ -3,5 +3,5 @@ require File.join(File.expand_path(File.dirname(__FILE__)), '../lib/network_mana
|
|
3
3
|
puts "Internet Connection: #{NetworkManager.internet_connection? ? 'yes' : 'no'}"
|
4
4
|
|
5
5
|
puts "States are described as NM_STATE_... in NetworkManager::DBus::Root"
|
6
|
-
puts "State is == #{NetworkManager::DBus::Root.instance.
|
6
|
+
puts "State is == #{NetworkManager::DBus::Root.instance.call('state'}"
|
7
7
|
|
data/lib/dbus_interface.rb
CHANGED
@@ -1,21 +1,30 @@
|
|
1
1
|
module DBusInterface
|
2
|
+
class UnavailableError < StandardError; end
|
3
|
+
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :interface
|
6
|
+
end
|
7
|
+
|
2
8
|
require 'dbus'
|
9
|
+
require File.join(File.dirname(__FILE__), 'dbus_interface/connection')
|
3
10
|
require File.join(File.dirname(__FILE__), 'dbus_interface/class')
|
4
11
|
require File.join(File.dirname(__FILE__), 'dbus_interface/object')
|
5
12
|
|
6
13
|
def self.system_bus
|
7
14
|
::DBus::SystemBus.instance
|
15
|
+
rescue Errno::ENOENT => e
|
16
|
+
raise UnavailableError.new "DBus SystemBus not available! (#{e})"
|
8
17
|
end
|
9
18
|
|
10
19
|
def self.service
|
11
|
-
@@service
|
20
|
+
@@service ||= system_bus.service config.interface
|
12
21
|
end
|
13
22
|
|
14
|
-
def self.
|
15
|
-
|
23
|
+
def self.configure(&block)
|
24
|
+
yield config
|
16
25
|
end
|
17
26
|
|
18
|
-
def self.
|
19
|
-
|
27
|
+
def self.config
|
28
|
+
@@config ||= Configuration.new
|
20
29
|
end
|
21
30
|
end
|
data/lib/dbus_interface/class.rb
CHANGED
@@ -2,14 +2,22 @@ module DBusInterface::Class
|
|
2
2
|
def map_dbus(conf)
|
3
3
|
@dbus ||= begin
|
4
4
|
# ensure hash
|
5
|
-
raise ArgumentError.new "
|
5
|
+
raise ArgumentError.new "map_dbus must receive a Hash instead of "\
|
6
6
|
"#{conf.class}" unless conf.is_a? Hash
|
7
7
|
# ensure :default_iface is set
|
8
|
-
raise ArgumentError.new "
|
8
|
+
raise ArgumentError.new "map_dbus must specify at least :default_iface"\
|
9
9
|
unless conf.has_key? :default_iface
|
10
10
|
conf
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
def no_properties!
|
15
|
+
@no_properties = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def no_properties?
|
19
|
+
defined?(@no_properties) && @no_properties ? true : false
|
20
|
+
end
|
13
21
|
|
14
22
|
def default_iface
|
15
23
|
dbus[:default_iface]
|
@@ -23,10 +31,26 @@ module DBusInterface::Class
|
|
23
31
|
def instance
|
24
32
|
@instance ||= new
|
25
33
|
end
|
26
|
-
|
34
|
+
|
35
|
+
def property(name, type = :string)
|
36
|
+
underscored = underscore(name)
|
37
|
+
define_method underscored do self[name] end
|
38
|
+
if type == :boolean
|
39
|
+
define_method "#{underscored}?" do self[name] ? true : false end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
27
43
|
private
|
28
44
|
|
29
45
|
def dbus
|
30
46
|
@dbus
|
31
47
|
end
|
32
|
-
|
48
|
+
|
49
|
+
def underscore(camel_cased_word)
|
50
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
51
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
52
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
53
|
+
tr("-", "_").
|
54
|
+
downcase
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class DBusInterface::Connection
|
2
|
+
attr_reader :default_iface, :object_path
|
3
|
+
|
4
|
+
def initialize(default_iface, object_path)
|
5
|
+
@default_iface = default_iface
|
6
|
+
@object_path = object_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.clear!
|
10
|
+
connections.clear
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.connections
|
14
|
+
@@connections ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.add_connection(con)
|
18
|
+
@@connections[con.key] = con
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.instance_for(default_iface, object_path)
|
22
|
+
con_key = connection_key(default_iface, object_path)
|
23
|
+
if connections[con_key]
|
24
|
+
connections[con_key]
|
25
|
+
else
|
26
|
+
new_con = new(default_iface, object_path)
|
27
|
+
add_connection(new_con)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.connection_key(default_iface, object_path)
|
32
|
+
[default_iface,object_path].join
|
33
|
+
end
|
34
|
+
|
35
|
+
def key
|
36
|
+
self.class.connection_key(default_iface, object_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.call(default_iface, object_path, method, *args)
|
40
|
+
con = instance_for(default_iface, object_path)
|
41
|
+
con.call(method, *args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def call(method, *args)
|
45
|
+
dbus.send(method, *args)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def dbus
|
51
|
+
@dbus ||= begin
|
52
|
+
d = DBusInterface.service.object(object_path)
|
53
|
+
d.default_iface = default_iface
|
54
|
+
d.introspect
|
55
|
+
d
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -3,17 +3,20 @@ module DBusInterface::Object
|
|
3
3
|
some_base.extend(DBusInterface::Class)
|
4
4
|
end
|
5
5
|
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
object
|
6
|
+
def call(method, *args)
|
7
|
+
if object_path == nil || object_path == '/'
|
8
|
+
nil
|
9
|
+
else
|
10
|
+
DBusInterface::Connection.call(self.class.default_iface, object_path, method, *args)
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
14
|
def properties
|
16
|
-
|
15
|
+
if self.class.no_properties?
|
16
|
+
nil
|
17
|
+
else
|
18
|
+
call('all_properties')
|
19
|
+
end
|
17
20
|
end
|
18
21
|
|
19
22
|
def initialize(object_path = nil)
|
@@ -32,4 +35,9 @@ module DBusInterface::Object
|
|
32
35
|
def [](key)
|
33
36
|
properties[key]
|
34
37
|
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
"#{self.class} #{properties}"
|
41
|
+
end
|
42
|
+
|
35
43
|
end
|
data/lib/network_manager.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# This Library provides an API based on the specs for network manager dbus api
|
2
2
|
# found here: http://projects.gnome.org/NetworkManager/developers/api/09/spec.html
|
3
|
+
require 'ipaddress'
|
3
4
|
module NetworkManager
|
4
5
|
# generic dbus api
|
5
6
|
require File.join(File.dirname(__FILE__), 'dbus_interface')
|
@@ -8,7 +9,7 @@ module NetworkManager
|
|
8
9
|
require File.join(File.dirname(__FILE__), 'network_manager/version')
|
9
10
|
|
10
11
|
# helper
|
11
|
-
require File.join(File.dirname(__FILE__), 'network_manager/
|
12
|
+
require File.join(File.dirname(__FILE__), 'network_manager/ip4_config')
|
12
13
|
|
13
14
|
# network manager dbus api
|
14
15
|
require File.join(File.dirname(__FILE__), 'network_manager/dbus')
|
@@ -23,6 +24,6 @@ module NetworkManager
|
|
23
24
|
end
|
24
25
|
|
25
26
|
DBusInterface.configure do |config|
|
26
|
-
config.
|
27
|
+
config.interface = 'org.freedesktop.NetworkManager'
|
27
28
|
end
|
28
29
|
end
|
data/lib/network_manager/dbus.rb
CHANGED
@@ -24,26 +24,28 @@ class NetworkManager::DBus::Device
|
|
24
24
|
# or LTE standards to access a cellular or wireline data network.
|
25
25
|
NM_DEVICE_TYPE_MODEM = 8
|
26
26
|
|
27
|
-
def to_s
|
28
|
-
"#{self.class} #{properties}"
|
29
|
-
end
|
30
|
-
|
31
27
|
def ip4_address
|
32
28
|
@ip_addr ||= begin
|
33
29
|
ip4_int = self['Ip4Address']
|
34
|
-
NetworkManager::
|
30
|
+
i = NetworkManager::Ip4Config.from_nm_au ip4_int
|
31
|
+
i.address
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
38
35
|
# @return [NetworkManager::DBus::Ip4Config] conf
|
39
36
|
def ip4_config
|
40
|
-
@ip4_config ||= NetworkManager::DBus::Ip4Config.new
|
37
|
+
@ip4_config ||= NetworkManager::DBus::Ip4Config.new self['Ip4Config']
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [NetworkManager::DBus::Ip4Config] conf
|
41
|
+
def dhcp4_config
|
42
|
+
@dhcp4_config ||= NetworkManager::DBus::Dhcp4Config.new self['Dhcp4Config']
|
41
43
|
end
|
42
44
|
|
43
45
|
# @return [NetworkManager::DBus::ActiveConnection] con
|
44
46
|
def active_connection
|
45
47
|
@active_connection ||=
|
46
|
-
NetworkManager::DBus::ActiveConnection.new
|
48
|
+
NetworkManager::DBus::ActiveConnection.new self['ActiveConnection']
|
47
49
|
end
|
48
50
|
|
49
51
|
#
|
@@ -2,7 +2,7 @@ class NetworkManager::DBus::Root
|
|
2
2
|
include DBusInterface::Object
|
3
3
|
map_dbus :default_iface => 'org.freedesktop.NetworkManager',
|
4
4
|
:object_path => '/org/freedesktop/NetworkManager'
|
5
|
-
|
5
|
+
|
6
6
|
# Networking state is unknown.
|
7
7
|
NM_STATE_UNKNOWN = 0
|
8
8
|
# Networking is inactive and all devices are disabled.
|
@@ -22,20 +22,24 @@ class NetworkManager::DBus::Root
|
|
22
22
|
|
23
23
|
# @return [Array<NetworkManager::DBus::Device>]] devices
|
24
24
|
def self.devices
|
25
|
-
instance.
|
25
|
+
instance.call('GetDevices').map do |list|
|
26
26
|
list.map do |object_path|
|
27
27
|
new_device(object_path)
|
28
28
|
end
|
29
29
|
end.flatten
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.activate_connection(con, dev, optional = NetworkManager::DBus::NULL_OBJECT)
|
33
|
+
instance.call('ActivateConnection', con.object_path, dev.object_path, optional)
|
34
|
+
end
|
35
|
+
|
32
36
|
def self.device_by_interface(interface)
|
33
|
-
paths = instance.
|
37
|
+
paths = instance.call('GetDeviceByIpIface', interface)
|
34
38
|
paths.empty? ? nil : new_device(paths.first)
|
35
39
|
end
|
36
40
|
|
37
41
|
def self.internet_connection?
|
38
|
-
instance.
|
42
|
+
instance.call('state').first == NM_STATE_CONNECTED_GLOBAL
|
39
43
|
end
|
40
44
|
|
41
45
|
private
|
@@ -3,19 +3,32 @@ class NetworkManager::DBus::Settings
|
|
3
3
|
map_dbus :default_iface => 'org.freedesktop.NetworkManager.Settings',
|
4
4
|
:object_path => '/org/freedesktop/NetworkManager/Settings'
|
5
5
|
|
6
|
+
# TODO methods
|
7
|
+
# GetConnectionByUuid
|
8
|
+
|
9
|
+
# TODO signals
|
10
|
+
# PropertiesChanged
|
11
|
+
|
12
|
+
property 'Hostname'
|
13
|
+
property 'CanModify', :boolean
|
14
|
+
|
6
15
|
def self.connections
|
7
|
-
instance.
|
16
|
+
instance.connections
|
17
|
+
end
|
18
|
+
|
19
|
+
def connections
|
20
|
+
call('ListConnections').map do |list|
|
8
21
|
list.map do |object_path|
|
9
22
|
::NetworkManager::DBus::SettingsConnection.new(object_path)
|
10
23
|
end
|
11
24
|
end.flatten
|
12
25
|
end
|
13
26
|
|
14
|
-
def
|
15
|
-
|
27
|
+
def add_connection(connection_hash)
|
28
|
+
call('AddConnection', connection_hash)
|
16
29
|
end
|
17
30
|
|
18
|
-
def hostname
|
19
|
-
|
31
|
+
def hostname=(new_name)
|
32
|
+
call('SaveHostname', new_name)
|
20
33
|
end
|
21
34
|
end
|