drbd 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.rdoc +53 -5
  2. data/VERSION +1 -1
  3. data/lib/drbd.rb +73 -20
  4. metadata +4 -4
data/README.rdoc CHANGED
@@ -10,34 +10,82 @@ Ruby wrapper for DRBD
10
10
 
11
11
  == Limitations
12
12
 
13
- * Just one-morning prototype
14
13
  * Best with drbd version > 8.3.7
14
+ * Hostname used for connection must be one of hostnames in drbd.conf (FQDN ideally)
15
+ * It'sJust one-morning's prototype, take patience
15
16
  * No tests
16
17
  * No documentation
17
18
  * Absolutely no warranty, use it at your own risk
18
19
 
20
+ == Installation
21
+
22
+ <code>gem install drbd</code>
19
23
 
20
- == How it works
21
24
 
25
+ == How it works
26
+ # simply fetch data from remote host
22
27
  d = Drbd.new("fqdn.domain.tld")
23
28
 
29
+ # you can specify command to be executed
30
+
31
+ d = Drbd.new("fqdn.domain.tld", :command => 'sudo /sbin/drbdadm')
32
+
33
+ # obtain array of configured resources
24
34
  r = d.resources.first
25
35
 
36
+ # get resource name
26
37
  r.name
27
38
 
39
+ # get resource protocol
40
+ r.protocol
41
+
42
+ # get hosts for resource
43
+ r.hosts
44
+
45
+ # get status for resource
46
+ r.status
47
+
48
+ # get node addresses
28
49
  r.hosts.map{|h| h.address }
29
50
 
51
+ # get status
52
+ # resource status is hash with keys:
53
+ # [:cs, :resynced_percent, :minor, :ro1, :ds1, :ro2, :ds2, :name]
30
54
  r.status
31
55
 
56
+ # find resource by name
32
57
  r = d.find_resource_by_name("r0")
33
58
 
34
- r.consinstent?
35
-
59
+ # find resource by backing disk
36
60
  r = d.find_resource_by_disk("/dev/volgroup-logvolume--name")
37
61
 
62
+ # true if both of devices are UpToDate
63
+ r.consinstent?
64
+
65
+ # true if resynced_percent is present in status
38
66
  r.resync_running?
39
67
 
40
- r.status[:resynced_percent]
68
+ # true if resource status is "Connected"
69
+ r.up?
70
+
71
+ # true if resource status is "Unconfigured"
72
+ r.down?
73
+
74
+ # perform drbdadm up on resource (use at your own risk!)
75
+ r.up!
76
+
77
+ # perform drbdadm down on resource (use at your own risk!)
78
+ r.down!
79
+
80
+ # perform forced drbdadm create-md on resource (use at your own risk!)
81
+ r.init_metadata
82
+
83
+
84
+ == TODO
85
+
86
+ * Replace IO.popen("ssh ...") with native ruby net/ssh
87
+ * Add states to actions (analyze exit status)
88
+ * Test suite
41
89
 
42
90
 
43
91
  == Copyright
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
data/lib/drbd.rb CHANGED
@@ -1,24 +1,29 @@
1
1
  require 'rubygems'
2
2
  require 'nokogiri'
3
3
  class DRBD
4
- attr_reader :resources
4
+ attr_reader :resources, :host, :command
5
5
 
6
- def initialize host
6
+ def initialize host, opts = {}
7
+ parse_opts opts
7
8
  @host = host
8
9
  load!
9
10
  end
10
11
 
12
+ def parse_opts opts
13
+ opts[:command].nil? ? @command = "sudo /sbin/drbdadm" : @command = opts[:command]
14
+ end
15
+
11
16
  def load!
12
17
  load_resources!
13
18
  load_status!
14
19
  end
15
20
 
16
21
  def load_resources!
17
- @resources = Config.new(IO.popen("ssh #{@host} \"sudo /sbin/drbdadm dump-xml\"")).resources
22
+ @resources = Resource.load_config(IO.popen("ssh #{@host} \"#{@command} dump-xml\""), self)
18
23
  end
19
24
 
20
25
  def load_status!
21
- raw_xml = IO.popen("ssh #{@host} \"sudo /sbin/drbdadm status\"")
26
+ raw_xml = IO.popen("ssh #{@host} \"#{@command} status\"")
22
27
  statuses = Status.new(raw_xml).resources
23
28
  set_resources_status statuses
24
29
  end
@@ -37,35 +42,33 @@ class DRBD
37
42
  def find_resource_by_disk disk_name
38
43
  @resources.select{|r| r.hosts.inject(false){|sum,h| (h.disk == disk_name && sum == false) ? true : sum}}.first
39
44
  end
40
-
41
- class Config
42
- attr_reader :xml
43
-
44
- def initialize xml
45
- @xml = Nokogiri::XML(xml)
46
- end
47
-
48
- def resources
49
- @xml.xpath("//config/resource").map{|r| Resource.new r }
50
- end
51
- end
52
-
45
+
53
46
  class Host
54
- attr_reader :name, :device, :disk, :address, :meta_disk
47
+ attr_reader :name, :device, :disk, :address, :meta_disk, :minor
55
48
  def initialize host
56
49
  @name = host['name']
57
50
  @device = host.xpath(".//device").text
51
+ @minor = host.xpath(".//device").attr("minor").value
58
52
  @disk = host.xpath(".//disk").text
59
53
  @address = host.xpath(".//address").text
54
+ @family = host.xpath(".//address").attr("family").value
55
+ @port = host.xpath(".//address").attr("port").value
60
56
  @meta_disk = host.xpath(".//meta-disk").text
61
57
  end
62
58
  end
63
59
 
64
60
  class Resource
65
- attr_reader :name, :device, :disk, :address, :meta_disk, :hosts
61
+ attr_reader :name, :protocol, :hosts, :drbd
66
62
  attr_accessor :status
67
- def initialize nokogiri_resource
63
+
64
+ def self.load_config raw, drbd
65
+ xml = Nokogiri::XML(raw)
66
+ xml.xpath("//config/resource").map{|r| Resource.new r, drbd }
67
+ end
68
+
69
+ def initialize nokogiri_resource, drbd
68
70
  xml = nokogiri_resource
71
+ @drbd = drbd
69
72
  @name = xml['name']
70
73
  @protocol = xml['protocol']
71
74
  @hosts = xml.xpath(".//host").to_a.map do |host_xml|
@@ -80,6 +83,53 @@ class DRBD
80
83
  def consistent?
81
84
  status[:ds1] == "UpToDate" && status[:ds2] == "UpToDate" && status[:resynced_percent] == nil
82
85
  end
86
+
87
+ def up?
88
+ status[:cs] == "Connected" || status[:cs] == "SyncTarget"
89
+ end
90
+
91
+ def down?
92
+ status[:cs] == "Unconfigured"
93
+ end
94
+
95
+ def up!
96
+ args = "up #{self.name}"
97
+ command = "ssh #{drbd.host} \"#{drbd.command} #{args}\""
98
+ system(command)
99
+ drbd.load_status!
100
+ end
101
+
102
+ def down!
103
+ args = "down #{self.name}"
104
+ command = "ssh #{drbd.host} \"#{drbd.command} #{args}\""
105
+ system(command)
106
+ drbd.load_status!
107
+ end
108
+
109
+ def init_metadata!
110
+ if self.down?
111
+ #drbdmeta 0 v08 /dev/mapper/dikobraz-www--emailmaster--cz_root_meta 0 create-md
112
+ command = "ssh #{drbd.host} \"sudo /sbin/drbdmeta --force #{local_minor} v08 #{local_host.meta_disk} 0 create-md\""
113
+ system(command)
114
+ return true
115
+ else
116
+ return false
117
+ end
118
+ end
119
+
120
+
121
+ def local_host
122
+ hosts.select{|h| h.name == drbd.host}.first
123
+ end
124
+
125
+ def local_minor
126
+ retrurn nil if local_host == nil
127
+ local_host.minor
128
+ end
129
+
130
+ def state
131
+ status[:cs]
132
+ end
83
133
  end
84
134
 
85
135
  class Status
@@ -105,3 +155,6 @@ class DRBD
105
155
  end
106
156
  end
107
157
 
158
+ D = DRBD.new("dikobraz.vmin.cz")
159
+ require 'irb'
160
+ IRB.start
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: drbd
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Adam Kliment
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-17 00:00:00 +01:00
18
+ date: 2011-01-18 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency