rubineti 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. data/.rvmrc +1 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +33 -0
  4. data/LICENSE +4 -0
  5. data/README.md +44 -0
  6. data/Rakefile +22 -0
  7. data/VERSION +1 -0
  8. data/lib/ganeti.rb +6 -0
  9. data/lib/rubineti/compute/cluster.rb +74 -0
  10. data/lib/rubineti/compute/instances.rb +245 -0
  11. data/lib/rubineti/compute/jobs.rb +42 -0
  12. data/lib/rubineti/compute/node.rb +140 -0
  13. data/lib/rubineti/compute.rb +125 -0
  14. data/lib/rubineti.rb +2 -0
  15. data/rubineti.gemspec +106 -0
  16. data/test/fixtures/cassettes/cluster_info.yml +96 -0
  17. data/test/fixtures/cassettes/cluster_oses.yml +32 -0
  18. data/test/fixtures/cassettes/cluster_redistribute_config.yml +32 -0
  19. data/test/fixtures/cassettes/cluster_version.yml +30 -0
  20. data/test/fixtures/cassettes/instance_create.yml +32 -0
  21. data/test/fixtures/cassettes/instance_delete.yml +30 -0
  22. data/test/fixtures/cassettes/instance_info.yml +30 -0
  23. data/test/fixtures/cassettes/instance_list.yml +93 -0
  24. data/test/fixtures/cassettes/instance_reboot.yml +32 -0
  25. data/test/fixtures/cassettes/instance_reinstall.yml +32 -0
  26. data/test/fixtures/cassettes/instance_shutdown.yml +32 -0
  27. data/test/fixtures/cassettes/instance_startup.yml +32 -0
  28. data/test/fixtures/cassettes/instances.yml +95 -0
  29. data/test/fixtures/cassettes/job_list.yml +135 -0
  30. data/test/fixtures/cassettes/jobs.yml +35 -0
  31. data/test/fixtures/cassettes/node_list.yml +55 -0
  32. data/test/fixtures/cassettes/node_role_list.yml +30 -0
  33. data/test/fixtures/cassettes/nodes.yml +39 -0
  34. data/test/lib/rubineti/compute/test_cluster.rb +71 -0
  35. data/test/lib/rubineti/compute/test_instances.rb +202 -0
  36. data/test/lib/rubineti/compute/test_jobs.rb +41 -0
  37. data/test/lib/rubineti/compute/test_node.rb +77 -0
  38. data/test/lib/rubineti/test_compute.rb +92 -0
  39. data/test/support.rb +35 -0
  40. metadata +225 -0
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.2-p0@rubineti
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "yajl-ruby", "~> 0.7.8"
4
+ gem "net-http-persistent", "~> 1.4.1"
5
+
6
+ group :development do
7
+ gem "rake"
8
+ gem "jeweler", "~> 1.5.1"
9
+ gem "vcr", "~> 1.3.3"
10
+ gem "webmock", "~> 1.6.1"
11
+ gem "minitest", "~> 2.0.0"
12
+ gem "mocha", "~> 0.9.10"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,33 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.2.2)
5
+ crack (0.1.8)
6
+ git (1.2.5)
7
+ jeweler (1.5.1)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ minitest (2.0.0)
12
+ mocha (0.9.10)
13
+ rake
14
+ net-http-persistent (1.4.1)
15
+ rake (0.8.7)
16
+ vcr (1.3.3)
17
+ webmock (1.6.1)
18
+ addressable (>= 2.2.2)
19
+ crack (>= 0.1.7)
20
+ yajl-ruby (0.7.8)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ jeweler (~> 1.5.1)
27
+ minitest (~> 2.0.0)
28
+ mocha (~> 0.9.10)
29
+ net-http-persistent (~> 1.4.1)
30
+ rake
31
+ vcr (~> 1.3.3)
32
+ webmock (~> 1.6.1)
33
+ yajl-ruby (~> 0.7.8)
data/LICENSE ADDED
@@ -0,0 +1,4 @@
1
+ "THE BEER-WARE LICENSE" (Revision 42):
2
+ <john@dewey.ws> wrote this file. As long as you retain this notice you
3
+ can do whatever you want with this stuff. If we meet some day, and you think
4
+ this stuff is worth it, you can buy me a beer in return John-B Dewey Jr.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # rubineti
2
+
3
+ [Ruby](http://www.ruby-lang.org/) bindings to [Ganeti's](http://code.google.com/p/ganeti/) Version 2 Remote API.
4
+
5
+ ## Usage
6
+
7
+ ### Bundler
8
+
9
+ gem "rubineti"
10
+
11
+ ### Examples
12
+
13
+ Initialize a connection
14
+
15
+ @connection = Rubineti::Compute.new :host => "ganeti.primary", :credentials => "fake:credentials"
16
+
17
+ View all jobs
18
+
19
+ @connection.jobs_list
20
+
21
+ Handling query params
22
+
23
+ @connection.instance_info "instance_name", :query => "bulk=1"
24
+
25
+ The responses are objectified [(by Yajl)](https://github.com/lloyd/yajl), and returned unmodified.
26
+
27
+ ## Testing
28
+
29
+ Tests can run offline thanks to [VCR](https://github.com/myronmarston/vcr).
30
+
31
+ $ bundle exec rake
32
+
33
+ ## Documents
34
+
35
+ * [Ganeti's remote API](http://docs.ganeti.org/ganeti/2.1/html/rapi.html)
36
+
37
+ ## Contributions
38
+
39
+ I have implemented the end-points immediately needed. Feel free to send me pull requests, if you
40
+ wish to help out.
41
+
42
+ ## Credits
43
+
44
+ Wesley Beary's [fog](https://github.com/geemus/fog), for which I referenced.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ begin
2
+ require "jeweler"
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "rubineti"
5
+ gem.summary = %Q{Ruby bindings to Ganeti's v2 Remote API.}
6
+ gem.email = "john@dewey.ws"
7
+ gem.homepage = "http://github.com/retr0h/rubineti"
8
+ gem.authors = ["retr0h"]
9
+ end
10
+ Jeweler::GemcutterTasks.new
11
+ rescue LoadError
12
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
13
+ end
14
+
15
+ require "rake/testtask"
16
+ Rake::TestTask.new(:test) do |test|
17
+ test.libs << "./lib" << "./test"
18
+ test.pattern = "test/**/test_*.rb"
19
+ test.verbose = true
20
+ end
21
+
22
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.2
data/lib/ganeti.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Ganeti
2
+ ##
3
+ # Remote API Version.
4
+
5
+ Version = 2
6
+ end
@@ -0,0 +1,74 @@
1
+ module Rubineti
2
+ module Cluster
3
+ ##
4
+ # Returns a list of features supported by the RAPI server.
5
+
6
+ def cluster_features
7
+ warn "WARNING: Cluster#cluster_features not implemented."
8
+ # get "/#{Ganeti::Version}/features"
9
+ end
10
+
11
+ ##
12
+ # Returns a list of cluster information.
13
+
14
+ def cluster_info
15
+ get "/#{Ganeti::Version}/info"
16
+ end
17
+
18
+ ##
19
+ # Redistribute configuration to all nodes.
20
+ # Returns a job_id.
21
+
22
+ def cluster_redistribute_config
23
+ put "/#{Ganeti::Version}/redistribute-config"
24
+ end
25
+
26
+ ##
27
+ # Adds a set of tags.
28
+ # Returns a job_id.
29
+ #
30
+ # If the optional dry-run parameter (?dry-run=1) is provided,
31
+ # the job will not be actually executed, only the pre-execution
32
+ # checks will be done.
33
+
34
+ def cluster_tags_create params = {}
35
+ warn "WARNING: Cluster#cluster_tags_create not implemented."
36
+ # put "/#{Ganeti::Version}/tags", params
37
+ end
38
+
39
+ ##
40
+ # Delete tags.
41
+ # Returns a job_id.
42
+ #
43
+ # If the optional dry-run parameter (?dry-run=1) is provided,
44
+ # the job will not be actually executed, only the pre-execution
45
+ # checks will be done.
46
+
47
+ def cluster_tags_delete params = {}
48
+ warn "WARNING: Cluster#cluster_tags_delete not implemented."
49
+ # delete "/#{Ganeti::Version}/tags", params
50
+ end
51
+
52
+ ##
53
+ # Returns the cluster tags.
54
+
55
+ def cluster_tags_list
56
+ warn "WARNING: Cluster#cluster_tags_list not implemented."
57
+ # get "/#{Ganeti::Version}/tags"
58
+ end
59
+
60
+ ##
61
+ # Returns the cluster API version.
62
+
63
+ def cluster_version
64
+ get "/version"
65
+ end
66
+
67
+ ##
68
+ # Return a list of all OSes.
69
+
70
+ def cluster_os_list
71
+ get "/#{Ganeti::Version}/os"
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,245 @@
1
+ module Rubineti
2
+ module Instances
3
+ ##
4
+ # Activate disks on an instance.
5
+ # Returns a job id.
6
+ #
7
+ # Takes the bool parameter ignore_size.
8
+ # (useful for forcing activation when recorded size is wrong).
9
+
10
+ def instance_activate_disks instance_name, params = {}
11
+ warn "WARNING: Instances#instance_activate_disks not implemented."
12
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/activate-disks", params
13
+ end
14
+
15
+ ##
16
+ # Creates an instance.
17
+ # Returns a job id.
18
+ #
19
+ # Body parameters:
20
+ # - http://docs.ganeti.org/ganeti/#{Ganeti::Version}.2/html/rapi.html#instances
21
+ #
22
+ # If the optional dry-run parameter (?dry-run=1) is provided,
23
+ # the job will not be actually executed, only the pre-execution
24
+ # checks will be done.
25
+
26
+ def instance_create params = {}
27
+ post "/#{Ganeti::Version}/instances", params
28
+ end
29
+
30
+ ##
31
+ # Deactivate disks on an instance.
32
+ # Returns a job id.
33
+
34
+ def instance_deactivate_disks instance_name
35
+ warn "WARNING: Instances#instance_deactivate_disks not implemented."
36
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/deactivate-disks"
37
+ end
38
+
39
+ ##
40
+ # Deletes an instance.
41
+ # Returns a job id.
42
+ #
43
+ # If the optional dry-run parameter (?dry-run=1) is provided,
44
+ # the job will not be actually executed, only the pre-execution
45
+ # checks will be done.
46
+
47
+ def instance_delete instance_name, params = {}
48
+ delete "/#{Ganeti::Version}/instances/#{instance_name}", params
49
+ end
50
+
51
+ ##
52
+ # Exports an instance.
53
+ # Returns a job id.
54
+ #
55
+ # Body parameters:
56
+ # - http://docs.ganeti.org/ganeti/#{Ganeti::Version}.2/html/rapi.html#instances-instance-name-export
57
+
58
+ def instance_export instance_name, params = {}
59
+ warn "WARNING: Instances#instance_export not implemented."
60
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/export", params
61
+ end
62
+
63
+ ##
64
+ # Requests detailed information about the instance.
65
+ #
66
+ # An optional parameter, static (bool), can be set to return only static
67
+ # information from the configuration without querying the instance’s nodes.
68
+ # The result will be a job id.
69
+
70
+ def instance_info instance_name, params = {}
71
+ get "/#{Ganeti::Version}/instances/#{instance_name}/info", params
72
+ end
73
+
74
+ ##
75
+ # Returns information about an instance, similar to
76
+ # the bulk output from +#instances_list+.
77
+
78
+ def instance_list instance_name
79
+ get "/#{Ganeti::Version}/instances/#{instance_name}"
80
+ end
81
+
82
+ ##
83
+ # Migrates an instance.
84
+ # Returns a job id.
85
+ #
86
+ # Body parameters:
87
+ # - http://docs.ganeti.org/ganeti/#{Ganeti::Version}.2/html/rapi.html#instances-instance-name-migrate
88
+
89
+ def instance_migrate instance_name, params = {}
90
+ warn "WARNING: Instances#instance_migrate not implemented."
91
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/migrate", params
92
+ end
93
+
94
+ ##
95
+ # Modifies an instance.
96
+ # Returns a job id.
97
+ #
98
+ # Body parameters:
99
+ # - http://docs.ganeti.org/ganeti/#{Ganeti::Version}.2/html/rapi.html#instances-instance-name-modify
100
+
101
+ def instance_modify instance_name, params = {}
102
+ warn "WARNING: Instances#instance_modify not implemented."
103
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/modify", params
104
+ end
105
+
106
+ ##
107
+ # Prepares an export of an instance.
108
+ # Returns a job id.
109
+ #
110
+ # Takes one parameter, mode, for the export mode.
111
+
112
+ def instance_prepare_export instance_name, params = {}
113
+ warn "WARNING: Instances#instance_prepare_export not implemented."
114
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/prepare-disks", params
115
+ end
116
+
117
+ ##
118
+ # Reboots the instance.
119
+ # Returns a job id.
120
+ #
121
+ # The URI takes optional type=soft|hard|full and ignore_secondaries=0|1 parameters.
122
+ # - soft is just a normal reboot, without terminating the hypervisor.
123
+ # - hard means full shutdown (including terminating the hypervisor process)
124
+ # and startup again.
125
+ # - full is like hard but also recreates the configuration from ground up
126
+ # as if you would have done a gnt-instance shutdown and gnt-instance start on it.
127
+ # - ignore_secondaries parameter (?ignore_secondaries=1), will start the
128
+ # instance even if secondary disks are failing.
129
+ #
130
+ # If the optional dry-run parameter (?dry-run=1) is provided,
131
+ # the job will not be actually executed, only the pre-execution
132
+ # checks will be done.
133
+
134
+ def instance_reboot instance_name, params = {}
135
+ post "/#{Ganeti::Version}/instances/#{instance_name}/reboot", params
136
+ end
137
+
138
+ ##
139
+ # Reinstalls the instance's operating system.
140
+ # Returns a job id.
141
+ #
142
+ # Takes the parameters os (OS template name) and nostartup (bool).
143
+
144
+ def instance_reinstall instance_name, params = {}
145
+ post "/#{Ganeti::Version}/instances/#{instance_name}/reinstall", params
146
+ end
147
+
148
+ ##
149
+ # Renames an instance.
150
+ # Returns a job id.
151
+ #
152
+ # Body parameters:
153
+ # - http://docs.ganeti.org/ganeti/#{Ganeti::Version}.2/html/rapi.html#instances-instance-name-rename
154
+
155
+ def instance_rename instance_name, params = {}
156
+ $stderr.print "WARNING: Instances#instance_rename not implemented."
157
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/rename", params
158
+ end
159
+
160
+ ##
161
+ # Replaces disks on an instance.
162
+ # Returns a job id.
163
+ #
164
+ # Takes the mandatory parameters mode:
165
+ # - (one of replace_on_primary, replace_on_secondary, replace_new_secondary or replace_auto),
166
+ # - disks (comma separated list of disk indexes)
167
+ # - remote_node and iallocator
168
+ #
169
+ # Either remote_node or iallocator needs to be defined when using mode=replace_new_secondary.
170
+ # replace_auto tries to determine the broken disk(s) on its own and replacing it.
171
+
172
+ def instance_replace_disks instance_name, params = {}
173
+ warn "WARNING: Instances#instance_replace_disks not implemented."
174
+ # post "/#{Ganeti::Version}/instances/#{instance_name}/replace-disks", params
175
+ end
176
+
177
+ ##
178
+ # Shutdown an instance.
179
+ # Returns a job id.
180
+ #
181
+ # If the optional dry-run parameter (?dry-run=1) is provided,
182
+ # the job will not be actually executed, only the pre-execution
183
+ # checks will be done.
184
+
185
+ def instance_shutdown instance_name, params = {}
186
+ put "/#{Ganeti::Version}/instances/#{instance_name}/shutdown", params
187
+ end
188
+
189
+ ##
190
+ # Returns a list of all available instances.
191
+ #
192
+ # If the optional bulk parameter (?bulk=1) is provided,
193
+ # the output contains detailed information about instances as a list.
194
+
195
+ def instances_list params = {}
196
+ get "/#{Ganeti::Version}/instances", params
197
+ end
198
+
199
+ ##
200
+ # Startup an instance.
201
+ # Returns a job id.
202
+ #
203
+ # If the optional dry-run parameter (?dry-run=1) is provided,
204
+ # the job will not be actually executed, only the pre-execution
205
+ # checks will be done.
206
+
207
+ def instance_startup instance_name, params = {}
208
+ put "/#{Ganeti::Version}/instances/#{instance_name}/startup", params
209
+ end
210
+
211
+ ##
212
+ # Add a set of tags.
213
+ # Returns a job id.
214
+ #
215
+ # If the optional dry-run parameter (?dry-run=1) is provided,
216
+ # the job will not be actually executed, only the pre-execution
217
+ # checks will be done.
218
+
219
+ def instance_tag_create instance_name, params = {}
220
+ warn "WARNING: Instances#instance_tag_create not implemented."
221
+ # put "/#{Ganeti::Version}/instances/#{instance_name}/tags", params
222
+ end
223
+
224
+ ##
225
+ # Delete a tag.
226
+ # Returns a job id.
227
+ #
228
+ # If the optional dry-run parameter (?dry-run=1) is provided,
229
+ # the job will not be actually executed, only the pre-execution
230
+ # checks will be done.
231
+
232
+ def instance_tag_delete instance_name, params = {}
233
+ warn "WARNING: Instances#instance_tag_delete not implemented."
234
+ # delete "/#{Ganeti::Version}/instances/#{instance_name}/tags", params
235
+ end
236
+
237
+ ##
238
+ # Return a list of tags.
239
+
240
+ def instance_tag_list instance_name, params = {}
241
+ warn "WARNING: Instances#instance_tag_list not implemented."
242
+ # get "/#{Ganeti::Version}/instances/#{instance_name}/tags", params
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,42 @@
1
+ module Rubineti
2
+ module Jobs
3
+ ##
4
+ # Returns an Array of all jobs.
5
+
6
+ def jobs_list
7
+ get "/#{Ganeti::Version}/jobs"
8
+ end
9
+
10
+ ##
11
+ # Returns a jobs status.
12
+ #
13
+ # +job_id+: A String of the 'job id'.
14
+
15
+ def job_list job_id
16
+ get "/#{Ganeti::Version}/jobs/#{job_id}"
17
+ end
18
+
19
+ ##
20
+ # Cancel a not-yet-started job.
21
+ #
22
+ # +job_id+: A String of the 'job id'.
23
+
24
+ def job_delete job_id
25
+ warn "WARNING: Jobs#job_delete not implemented."
26
+ # delete "/#{Ganeti::Version}/jobs/#{job_id}/delete"
27
+ end
28
+
29
+ ##
30
+ # Waits for changes on a job.
31
+ #
32
+ # +job_id+: A String of the 'job id'.
33
+ #
34
+ # Body parameters:
35
+ # - http://docs.ganeti.org/ganeti/#{Ganeti::Version}.1/html/rapi.html#jobs-job-id-wait
36
+
37
+ def job_wait job_id, params = {}
38
+ warn "WARNING: Jobs#job_wait not implemented."
39
+ # get "/#{Ganeti::Version}/jobs/#{job_id}/wait", params
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,140 @@
1
+ module Rubineti
2
+ module Node
3
+
4
+ ##
5
+ # Evacuates all secondary instances off a node.
6
+ #
7
+ # To evacuate a node, either one of the iallocator or remote_node parameters must be passed:
8
+ # - evacuate?iallocator=[iallocator]
9
+ # - evacuate?remote_node=[nodeX.example.com]
10
+ # See: http://docs.ganeti.org/ganeti/2.2/html/rapi.html#nodes-node-name-evacuate
11
+ #
12
+ # If the optional dry-run parameter (?dry-run=1) is provided,
13
+ # the job will not be actually executed, only the pre-execution
14
+ # checks will be done.
15
+
16
+ def node_evacuate node_name, params = {}
17
+ warn "WARNING: Node#node_evacuate not implemented."
18
+ # post "/2/nodes/#{node_name}/evacuate", params
19
+ end
20
+
21
+ ##
22
+ # Returns information about a node.
23
+
24
+ def node_list node_name
25
+ get "/2/nodes/#{node_name}"
26
+ end
27
+
28
+ ##
29
+ # Migrates all primary instances from a node.
30
+ #
31
+ # If no mode is explicitly specified, each instances’ hypervisor
32
+ # default migration mode will be used. Query parameters:
33
+ # - live (bool): If set, use live migration if available.
34
+ # - mode (string): Sets migration mode, live for live migration
35
+ # and non-live for non-live migration. Supported by Ganeti 2.2 and above.
36
+
37
+ def node_migrate node_name, params = {}
38
+ warn "WARNING: Node#node_migrate not implemented."
39
+ # post "/2/nodes/#{node_name}/migrate", params
40
+ end
41
+
42
+ ##
43
+ # Change the node role.
44
+ # Returns a job id.
45
+ #
46
+ # It supports the bool force argument.
47
+
48
+ def node_role_create node_name
49
+ warn "WARNING: Node#node_role_create not implemented."
50
+ # TODO: API Docs do not describe it's usage well.
51
+ # put "/2/nodes/#{node_name}/role"
52
+ end
53
+
54
+ ##
55
+ # Returns the current node role.
56
+
57
+ def node_role_list node_name
58
+ get "/2/nodes/#{node_name}/role"
59
+ end
60
+
61
+ ##
62
+ # Returns a list of all nodes.
63
+ #
64
+ # If the optional bulk parameter (?bulk=1) is provided,
65
+ # the output contains detailed information about instances as a list.
66
+
67
+ def nodes_list params = {}
68
+ get "/2/nodes", params
69
+ end
70
+
71
+ ##
72
+ # Requests a list of storage units on a node.
73
+ # Returns a job id.
74
+ #
75
+ # Requires the parameters storage_type (one of file, lvm-pv or lvm-vg) and output_fields.
76
+
77
+ def node_storage_list node_name, params = {}
78
+ warn "WARNING: Node#node_storage_list not implemented."
79
+ # get "/2/nodes/#{node_name}/storage", params
80
+ end
81
+
82
+ ##
83
+ # Modifies storage units on the node.
84
+ # Returns a job id.
85
+ #
86
+ # Requires the parameters storage_type (one of file, lvm-pv or lvm-vg) and name (name of the storage unit).
87
+ # Parameters can be passed additionally. Currently only allocatable (bool) is supported.
88
+
89
+ def node_storage_modify node_name, params = {}
90
+ warn "WARNING: Node#node_storage_modify not implemented."
91
+ # put "/2/nodes/#{node_name}/storage/modify", params
92
+ end
93
+
94
+ ##
95
+ # Repairs a storage unit on the node.
96
+ # Returns a job id.
97
+ #
98
+ # Requires the parameters storage_type (currently only lvm-vg can be repaired) and
99
+ # name (name of the storage unit).
100
+
101
+ def node_storage_repair node_name, params = {}
102
+ warn "WARNING: Node#node_storage_repair not implemented."
103
+ # put "/2/nodes/#{node_name}/repair", params
104
+ end
105
+
106
+ ##
107
+ # Add a set of tags.
108
+ # Returns a job id.
109
+ #
110
+ # If the optional dry-run parameter (?dry-run=1) is provided,
111
+ # the job will not be actually executed, only the pre-execution
112
+ # checks will be done.
113
+
114
+ def node_tags_create node_name, params = {}
115
+ warn "WARNING: Node#node_tags_create not implemented."
116
+ # put "/2/nodes/#{node_name}/tags", params
117
+ end
118
+
119
+ ##
120
+ # Deletes tags.
121
+ # Returns a job id.
122
+ #
123
+ # If the optional dry-run parameter (?dry-run=1) is provided,
124
+ # the job will not be actually executed, only the pre-execution
125
+ # checks will be done.
126
+
127
+ def node_tags_delete node_name, params = {}
128
+ warn "WARNING: Node#node_tags_delete not implemented."
129
+ # delete "/2/nodes/#{node_name}/tags", params
130
+ end
131
+
132
+ ##
133
+ # Return a list of tags.
134
+
135
+ def node_tags_list node_name
136
+ warn "WARNING: Node#node_tags_list not implemented."
137
+ # get "/2/nodes/#{node_name}/tags"
138
+ end
139
+ end
140
+ end