azure-armrest 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,359 @@
1
+ # Azure namespace
2
+ module Azure
3
+ # Armrest namespace
4
+ module Armrest
5
+ # Base class for managing virtual machines
6
+ class VirtualMachineManager < ArmrestManager
7
+
8
+ # The provider used in requests when gathering VM information.
9
+ attr_reader :provider
10
+
11
+ # Create and return a new VirtualMachineManager (VMM) instance. Most
12
+ # methods for a VMM instance will return one or more VirtualMachine
13
+ # instances.
14
+ #
15
+ # This subclass accepts the additional :provider option as well. The
16
+ # default is 'Microsoft.ClassicCompute'. You may need to set this to
17
+ # 'Microsoft.Compute' for your purposes.
18
+ #
19
+ def initialize(options = {})
20
+ super
21
+
22
+ @provider = options[:provider] || 'Microsoft.Compute'
23
+
24
+ # Typically only empty in testing.
25
+ unless @@providers.empty?
26
+ @api_version = @@providers[@provider]['virtualMachines']['api_version']
27
+ end
28
+ end
29
+
30
+ # Set a new provider to use the default for other methods. This may alter
31
+ # the api_version used for future requests. In practice, only
32
+ # 'Microsoft.Compute' or 'Microsoft.ClassicCompute' should be used.
33
+ #
34
+ def provider=(name)
35
+ @api_version = @@providers[name]['virtualMachines']['api_version']
36
+ @provider = name
37
+ end
38
+
39
+ # Return a list of available VM series (aka sizes, flavors, etc), such
40
+ # as "Basic_A1", though information is included as well.
41
+ #
42
+ def series(location)
43
+ unless @@providers[@provider] && @@providers[@provider]['locations/vmSizes']
44
+ raise ArgumentError, "Invalid provider '#{provider}'"
45
+ end
46
+
47
+ version = @@providers[@provider]['locations/vmSizes']['api_version']
48
+
49
+ url = url_with_api_version(
50
+ version, @base_url, 'subscriptions', subscription_id, 'providers',
51
+ provider, 'locations', location, 'vmSizes'
52
+ )
53
+
54
+ JSON.parse(rest_get(url))['value']
55
+ end
56
+
57
+ alias sizes series
58
+
59
+ # Returns a list of available virtual machines for the given subscription
60
+ # for the provided +group+, or all resource groups if none is provided.
61
+ #
62
+ # Examples:
63
+ #
64
+ # # Get VM's for all resource groups
65
+ # vmm.list
66
+ #
67
+ # # Get VM's only for a specific group
68
+ # vmm.list('some_group')
69
+ #--
70
+ # The specific hashes we can grab are:
71
+ # p JSON.parse(resp.body)["value"][0]["properties"]["instanceView"]
72
+ # p JSON.parse(resp.body)["value"][0]["properties"]["hardwareProfile"]
73
+ # p JSON.parse(resp.body)["value"][0]["properties"]["storageProfile"]
74
+ #
75
+ def list(group = nil)
76
+ array = []
77
+ if group
78
+ url = build_url(group)
79
+ array << JSON.parse(rest_get(url))['value']
80
+ else
81
+ threads = []
82
+ mutex = Mutex.new
83
+
84
+ resource_groups.each do |group|
85
+ url = build_url(group['name'])
86
+
87
+ threads << Thread.new(url) do |thread_url|
88
+ response = rest_get(thread_url)
89
+ result = JSON.parse(response)['value']
90
+ mutex.synchronize{ array << result if result }
91
+ end
92
+ end
93
+
94
+ threads.each(&:join)
95
+
96
+ array = array.flatten
97
+ end
98
+
99
+ add_network_profile(array)
100
+ end
101
+
102
+ alias get_vms list
103
+
104
+ def add_network_profile(vms)
105
+ vms.each { |vm|
106
+ vm['properties']['networkProfile']['networkInterfaces'].each { |net|
107
+ get_nic_profile(net)
108
+ }
109
+ }
110
+ end
111
+
112
+ def get_nic_profile(nic)
113
+ url = File.join(
114
+ Azure::Armrest::RESOURCE,
115
+ nic['id'],
116
+ "?api-version=#{api_version}"
117
+ )
118
+
119
+ nic['properties'] = JSON.parse(rest_get(url))['properties']['ipConfigurations']
120
+ nic['properties'].each do |n|
121
+ next if n['properties']['publicIPAddress'].nil?
122
+
123
+ # public IP is a URI so we need to make another rest call to get it.
124
+ url = File.join(
125
+ Azure::Armrest::RESOURCE,
126
+ n['properties']['publicIPAddress']['id'],
127
+ "?api-version=#{api_version}"
128
+ )
129
+
130
+ public_ip = JSON.parse(rest_get(url))['properties']['ipAddress']
131
+ n['properties']['publicIPAddress'] = public_ip
132
+ end
133
+ end
134
+
135
+ # Captures the +vmname+ and associated disks into a reusable CSM template.
136
+ #--
137
+ # POST
138
+ def capture(vmname, action = 'capture')
139
+ uri = @uri + "/#{vmname}/#{action}?api-version=#{api_version}"
140
+ uri
141
+ end
142
+
143
+ # Creates a new virtual machine (or updates an existing one). Pass a hash
144
+ # of options to configure the VM as you see fit. Some options are
145
+ # mandatory. The following are a list of possible options:
146
+ #
147
+ # - :name
148
+ # Required. The name of the virtual machine. The name must be unique
149
+ # within the availability set that it belongs to.
150
+ #
151
+ # - :location
152
+ # Required. The location where the VM should be created, e.g. "West US".
153
+ #
154
+ # - :tags
155
+ # Optional. Specifies an identifier for the availability set.
156
+ #
157
+ # - :hardwareprofile
158
+ # Required. Contains a collection of hardware settings for the VM.
159
+ #
160
+ # - :vmsize
161
+ # Required. Specifies the size of the virtual machine. Possible
162
+ # sizes are Standard_A0..Standard_A4.
163
+ #
164
+ # - :osprofile
165
+ # Required. Contains a collection of settings for the OS configuration
166
+ # which must contain all of the following:
167
+ #
168
+ # - :computername
169
+ # - :adminusername
170
+ # - :adminpassword
171
+ # - :username
172
+ # - :password
173
+ #
174
+ # - :storageprofile
175
+ # Required. Contains a collection of settings for storage and disk
176
+ # settings for the VM. You must specify an :osdisk and :name. The
177
+ # :datadisks setting is optional.
178
+ #
179
+ # - :osdisk
180
+ # Required. Contains a collection of settings for the operating
181
+ # system disk.
182
+ #
183
+ # - :name
184
+ # - :ostype
185
+ # - :caching
186
+ # - :image
187
+ # - :vhd
188
+ #
189
+ # - :datadisks
190
+ # Optional. Contains a collection of settings for data disks.
191
+ #
192
+ # - :name
193
+ # - :image
194
+ # - :vhd
195
+ # - :lun
196
+ # - :caching
197
+ #
198
+ # - :name
199
+ # Required. Specifies the name of the disk.
200
+ #
201
+ # For clarity, we recommend using the update method for existing VM's.
202
+ #
203
+ # Example:
204
+ #
205
+ # vmm = VirtualMachineManager.new(x, y, z)
206
+ #
207
+ # vm = vmm.create(
208
+ # :name => 'test1',
209
+ # :location => 'West US',
210
+ # :hardwareprofile => {:vmsize => 'Standard_A0'},
211
+ # :osprofile => {
212
+ # :computername => 'some_name',
213
+ # :adminusername => 'admin_user',
214
+ # :adminpassword => 'adminxxxxxx',
215
+ # :username => 'some_user',
216
+ # :password => 'userpassxxxxxx',
217
+ # },
218
+ # :storageprofile => {
219
+ # :osdisk => {
220
+ # :ostype => 'Windows',
221
+ # :caching => 'Read'
222
+ # }
223
+ # }
224
+ # )
225
+ #--
226
+ # PUT operation
227
+ #
228
+ def create(options = {})
229
+ #name = options.fetch(:name)
230
+ #location = options.fetch(:location)
231
+ #tags = option[:tags]
232
+ vmsize = options.fetch(:vmsize)
233
+
234
+ unless VALID_VM_SIZES.include?(vmsize)
235
+ raise ArgumentError, "Invalid vmsize '#{vmsize}'"
236
+ end
237
+ end
238
+
239
+ alias update create
240
+
241
+ # Stop the VM +vmname+ in +group+ and deallocate the tenant in Fabric.
242
+ #
243
+ def deallocate(vmname, group = vmname)
244
+ url = build_url(group, vmname, 'deallocate')
245
+ response = rest_post(url)
246
+ response.return!
247
+ end
248
+
249
+ # Deletes the +vmname+ in +group+ that you specify. Note that associated
250
+ # disks are not deleted.
251
+ #
252
+ def delete(vmname, group = vmname)
253
+ url = build_url(group, vmname)
254
+ response = rest_delete(url)
255
+ response.return!
256
+ end
257
+
258
+ # Sets the OSState for the +vmname+ in +group+ to 'Generalized'.
259
+ #
260
+ def generalize(vmname, group = vmname)
261
+ url = build_url(group, vmname, 'generalize')
262
+ response = rest_post(url)
263
+ response.return!
264
+ end
265
+
266
+ # Retrieves the settings of the VM named +vmname+ in resource group
267
+ # +group+, which will default to the same as the name of the VM.
268
+ #
269
+ # By default this method will retrieve the model view. If the +model_view+
270
+ # parameter is false, it will retrieve an instance view. The difference is
271
+ # in the details of the information retrieved.
272
+ #
273
+ def get(vmname, group = vmname, model_view = true)
274
+ if model_view
275
+ url = build_url(group, vmname)
276
+ else
277
+ url = build_url(group, vmname, 'instanceView')
278
+ end
279
+
280
+ JSON.parse(rest_get(url))
281
+ end
282
+
283
+ # Convenient wrapper around the get method that retrieves the model view
284
+ # for +vmname+ in resource_group +group+.
285
+ #
286
+ def get_model_view(vmname, group = vmname)
287
+ get(vmname, group, true)
288
+ end
289
+
290
+ # Convenient wrapper around the get method that retrieves the instance view
291
+ # for +vmname+ in resource_group +group+.
292
+ #
293
+ def get_instance_view(vmname, group = vmname)
294
+ get(vmname, group, false)
295
+ end
296
+
297
+ # Restart the VM +vmname+ for the given +group+, which will default
298
+ # to the same as the vmname.
299
+ #
300
+ # This is an asynchronous operation that returns a response object
301
+ # which you can inspect, such as response.code or response.headers.
302
+ #
303
+ def restart(vmname, group = vmname)
304
+ url = build_url(group, vmname, 'restart')
305
+ response = rest_post(url)
306
+ response.return!
307
+ end
308
+
309
+ # Start the VM +vmname+ for the given +group+, which will default
310
+ # to the same as the vmname.
311
+ #
312
+ # This is an asynchronous operation that returns a response object
313
+ # which you can inspect, such as response.code or response.headers.
314
+ #
315
+ def start(vmname, group = vmname)
316
+ url = build_url(group, vmname, 'start')
317
+ response = rest_post(url)
318
+ response.return!
319
+ end
320
+
321
+ # Stop the VM +vmname+ for the given +group+ gracefully. However,
322
+ # a forced shutdown will occur after 15 minutes.
323
+ #
324
+ # This is an asynchronous operation that returns a response object
325
+ # which you can inspect, such as response.code or response.headers.
326
+ #
327
+ def stop(vmname, group = vmname)
328
+ url = build_url(group, vmname, 'powerOff')
329
+ response = rest_post(url)
330
+ response.return!
331
+ end
332
+
333
+ private
334
+
335
+ # If no default subscription is set, then use the first one found.
336
+ def set_default_subscription
337
+ @subscription_id ||= subscriptions.first['subscriptionId']
338
+ end
339
+
340
+ # Builds a URL based on subscription_id an resource_group and any other
341
+ # arguments provided, and appends it with the api_version.
342
+ #
343
+ def build_url(resource_group, *args)
344
+ url = File.join(
345
+ Azure::Armrest::COMMON_URI,
346
+ subscription_id,
347
+ 'resourceGroups',
348
+ resource_group,
349
+ 'providers',
350
+ @provider,
351
+ 'virtualMachines',
352
+ )
353
+
354
+ url = File.join(url, *args) unless args.empty?
355
+ url << "?api-version=#{api_version}"
356
+ end
357
+ end
358
+ end
359
+ end
@@ -0,0 +1,62 @@
1
+ # Azure namespace
2
+ module Azure
3
+ # Armrest namespace
4
+ module Armrest
5
+ # Base class for managing virtual networks
6
+ class VirtualNetworkManager < ArmrestManager
7
+
8
+ # Create and return a new VirtualNetworkManager instance. Most
9
+ # methods for a VirtualNetworkManager instance will return one or
10
+ # more VirtualNetwork instances.
11
+ #
12
+ def initialize(options = {})
13
+ super
14
+
15
+ @base_url += "resourceGroups/#{@resource_group}/"
16
+ @base_url += "providers/Microsoft.Network/virtualNetworks"
17
+ end
18
+
19
+ # Creates a new virtual network using the given +options+. The possible
20
+ # options are:
21
+ #
22
+ # :name
23
+ # :id
24
+ # :location
25
+ # :tags
26
+ # :etag
27
+ # :properties
28
+ # :address_space
29
+ # :address_prefixes
30
+ # :dhcp_options
31
+ # :dns_servers
32
+ # :subnets
33
+ # :name
34
+ # :id
35
+ # :etag
36
+ # :provisioning_state
37
+ # :address_prefix
38
+ # :dhcp_options
39
+ # :ip_configurations
40
+ # :id
41
+ #--
42
+ def create(network_name, options = {})
43
+ @uri += "/#{network_name}?api-version=#{api_version}"
44
+ end
45
+
46
+ # Deletes the +network_name+ availability set.
47
+ def delete(network_name)
48
+ @uri += "/#{network_name}?api-version=#{api_version}"
49
+ end
50
+
51
+ # Retrieves the options of an availability set.
52
+ def get(network_name)
53
+ @uri += "/#{network_name}?api-version=#{api_version}"
54
+ end
55
+
56
+ # List availability sets.
57
+ def list
58
+ @uri += "?api-version=#{api_version}"
59
+ end
60
+ end
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: azure-armrest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Daniel J. Berger
8
+ - Bronagh Sorota
9
+ - Greg Blomquist
10
+ autorequire:
11
+ bindir: exe
12
+ cert_chain: []
13
+ date: 2015-08-13 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '10.0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '10.0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rspec
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '3.0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: codeclimate-test-reporter
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: json
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: rest-client
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :runtime
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ description: |
100
+ This is a Ruby interface for Azure using the newer REST API. This is
101
+ different than the current azure gem, which uses the older (XML) interface
102
+ behind the scenes.
103
+ email:
104
+ - dberger@redhat.com
105
+ - bsorota@redhat.com
106
+ - gblomqui@redhat.com
107
+ executables: []
108
+ extensions: []
109
+ extra_rdoc_files: []
110
+ files:
111
+ - ".gitignore"
112
+ - ".rspec"
113
+ - ".travis.yml"
114
+ - CHANGES
115
+ - Gemfile
116
+ - LICENSE
117
+ - README.md
118
+ - Rakefile
119
+ - azure-armrest.gemspec
120
+ - lib/azure-armrest.rb
121
+ - lib/azure/armrest.rb
122
+ - lib/azure/armrest/armrest_manager.rb
123
+ - lib/azure/armrest/availability_set_manager.rb
124
+ - lib/azure/armrest/event_manager.rb
125
+ - lib/azure/armrest/storage_account_manager.rb
126
+ - lib/azure/armrest/subnet_manager.rb
127
+ - lib/azure/armrest/version.rb
128
+ - lib/azure/armrest/virtual_machine_extension_manager.rb
129
+ - lib/azure/armrest/virtual_machine_image_manager.rb
130
+ - lib/azure/armrest/virtual_machine_manager.rb
131
+ - lib/azure/armrest/virtual_network_manager.rb
132
+ homepage: http://github.com/ManageIQ/azure-armrest
133
+ licenses:
134
+ - Apache 2.0
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.4.8
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: An interface for ARM/JSON Azure REST API
156
+ test_files: []
157
+ has_rdoc: