azurex 0.6.6 → 0.6.7

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/Gemfile +1 -1
  4. data/README.md +2 -0
  5. data/lib/azure.rb +3 -0
  6. data/lib/azure/base_management/management_http_request.rb +3 -3
  7. data/lib/azure/cloud_service_management/cloud_service_management_service.rb +1 -9
  8. data/lib/azure/core/utility.rb +0 -71
  9. data/lib/azure/storage_management/serialization.rb +9 -12
  10. data/lib/azure/storage_management/storage_account.rb +1 -0
  11. data/lib/azure/storage_management/storage_management_service.rb +15 -18
  12. data/lib/azure/version.rb +1 -1
  13. data/lib/azure/virtual_machine_image_management/serialization.rb +15 -1
  14. data/lib/azure/virtual_machine_image_management/virtual_machine_image_management_service.rb +31 -2
  15. data/lib/azure/virtual_machine_management/serialization.rb +1 -1
  16. data/lib/azure/virtual_machine_management/virtual_machine_management_service.rb +4 -4
  17. data/lib/core_ext/ip_addr.rb +48 -0
  18. data/lib/core_ext/string.rb +27 -0
  19. data/test/fixtures/get_storage_account_properties.xml +6 -4
  20. data/test/fixtures/list_storage_accounts.xml +2 -0
  21. data/test/fixtures/list_vmimages.xml +86 -0
  22. data/test/fixtures/updated_storage_accounts.xml +2 -0
  23. data/test/integration/affinity_group/Create_Affinity_test.rb +1 -1
  24. data/test/integration/cloud_service/Cloud_Delete_test.rb +2 -2
  25. data/test/integration/storage_management/storage_management_test.rb +40 -33
  26. data/test/integration/vm/VM_Delete_test.rb +1 -1
  27. data/test/integration/vm_image/virtual_machine_image_test.rb +1 -1
  28. data/test/unit/cloud_service_management/cloud_service_management_service_test.rb +4 -4
  29. data/test/unit/core_ext/string_test.rb +11 -0
  30. data/test/unit/storage_management/serialization_test.rb +12 -13
  31. data/test/unit/storage_management/storage_management_service_test.rb +26 -40
  32. data/test/unit/virtual_machine_image_management/serialization_test.rb +17 -1
  33. data/test/unit/virtual_machine_image_management/virtual_machine_image_management_service_test.rb +113 -8
  34. data/test/unit/virtual_machine_management/virtual_machine_management_service_test.rb +17 -0
  35. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c96ccd80aafb20085d1e9b30e35c0546542f1ef1
4
- data.tar.gz: c383e6867d9e57d804bdb2d2134fad00a56b4250
3
+ metadata.gz: 97ea989a0ffca5af37573d3c744b46a0f104d820
4
+ data.tar.gz: fc1a69389027cb0816ddcce59acdbcdebc797f3a
5
5
  SHA512:
6
- metadata.gz: 6c8d74bd5d0fa9754e3b30071a5c4e984235418cbd365d99537670b75c2ed091b62e9bd29112b92fc8abb9e076f1f6973657adddb56efa16d38b034775a07c44
7
- data.tar.gz: 48b7d6a731e96eacf0eb477e9b7d334a157e17176da345450de705d2e4425e2d4c57381c7265499b9023171bcff579f0cc3d60f052414553c40f327d9230c7df
6
+ metadata.gz: b205dad74df5dd56dae98fcc09dfea3026cfa050681d8719f935296e09a4d538c50d04b35b792927b631cd6f8bb47bb33b5b72161fd5bb72d53e097e2c0947e3
7
+ data.tar.gz: d6156443d72df0cb806a23d57a82eb8f7fea63d7ed9f7b47d97bd5d4fa0e2b363ebffffe561f56bb3b83bd9783b98a5c371e2ea8b3ce700e43a0e2e6192a65f9
data/.gitignore CHANGED
@@ -10,4 +10,6 @@ nbproject/*
10
10
  *.orig
11
11
 
12
12
 
13
- .DS_Store
13
+ .DS_Store
14
+ .ruby-version
15
+ .ruby-gemset
data/Gemfile CHANGED
@@ -13,4 +13,4 @@
13
13
  # limitations under the License.
14
14
  #--------------------------------------------------------------------------
15
15
  source 'https://rubygems.org'
16
- gemspec
16
+ gemspec
data/README.md CHANGED
@@ -9,6 +9,8 @@ This repo has the following enhancements over the original:
9
9
  * Provision VMs from custom images
10
10
  * More webhooks for cloud services
11
11
  * Access more attributes from virtual machines
12
+ * CustomData for virtual machines
13
+ * Support for the A8, A9 and 'D' series VM sizes
12
14
 
13
15
  There are three goals for this repo:
14
16
 
@@ -14,6 +14,7 @@
14
14
  #--------------------------------------------------------------------------
15
15
  module Azure; end
16
16
 
17
+ # The order that files are required in is important...
17
18
  require 'azure/core'
18
19
  require 'azure/blob/blob_service'
19
20
  require 'azure/queue/queue_service'
@@ -37,6 +38,8 @@ require 'azure/cloud_service_management/cloud_service_management_service'
37
38
  require 'azure/base_management/location'
38
39
  require 'azure/sql_database_management/sql_database_management_service'
39
40
  require 'azure/virtual_network_management/virtual_network_management_service'
41
+ require 'core_ext/string'
42
+ require 'core_ext/ip_addr'
40
43
 
41
44
  # add some aliases for convenience
42
45
  Azure::BlobService = Azure::Blob::BlobService
@@ -35,7 +35,7 @@ module Azure
35
35
  @warn = false
36
36
  content_length = body ? body.bytesize.to_s : '0'
37
37
  @headers = {
38
- 'x-ms-version' => '2014-05-01',
38
+ 'x-ms-version' => '2014-06-01',
39
39
  'Content-Type' => 'application/xml',
40
40
  'Content-Length' => content_length
41
41
  }
@@ -156,7 +156,7 @@ module Azure
156
156
  #
157
157
  # * +request_id+ - String. x-ms-request-id response header of request
158
158
  #
159
- # See: http://msdn.microsoft.com/en-us/library/windowsazure/ee460783.aspx
159
+ # See: http://msdn.microsoft.com/en-us/library/azure/ee460783.aspx
160
160
  #
161
161
  # Print Error or Success of Operation.
162
162
  def check_completion(request_id)
@@ -241,4 +241,4 @@ module Azure
241
241
  end
242
242
  end
243
243
  end
244
- end
244
+ end
@@ -297,15 +297,7 @@ module Azure
297
297
  # If true, the cloud service is available. If false, the cloud service
298
298
  # does not exist.
299
299
  def get_cloud_service(name)
300
- return false if name.nil?
301
- flag = false
302
- list_cloud_services.each do |cloud_service|
303
- if cloud_service.name == name
304
- flag = true
305
- break
306
- end
307
- end
308
- flag
300
+ list_cloud_services.select { |x| x.name.casecmp(name) == 0 }.first
309
301
  end
310
302
 
311
303
  def get_cloud_service_properties(name)
@@ -117,74 +117,3 @@ module Azure
117
117
  end
118
118
  end
119
119
 
120
- class String
121
- { reset: 0,
122
- bold: 1,
123
- dark: 2,
124
- underline: 4,
125
- blink: 5,
126
- orange: 6,
127
- negative: 7,
128
- black: 30,
129
- red: 31,
130
- green: 32,
131
- yellow: 33,
132
- blue: 34,
133
- magenta: 35,
134
- cyan: 36,
135
- white: 37,
136
- }.each do |key, value|
137
- define_method key do
138
- "\e[#{value}m" + self + "\e[0m"
139
- end
140
- end
141
- end
142
-
143
- # Code validate private/public IP acceptable ranges.
144
- class IPAddr
145
- PRIVATE_RANGES = [
146
- IPAddr.new('10.0.0.0/8'),
147
- IPAddr.new('172.16.0.0/12'),
148
- IPAddr.new('192.168.0.0/16')
149
- ]
150
-
151
- def private?
152
- return false unless self.ipv4?
153
- PRIVATE_RANGES.each do |ipr|
154
- return true if ipr.include?(self)
155
- end
156
- false
157
- end
158
-
159
- def public?
160
- !private?
161
- end
162
-
163
- class << self
164
- def validate_ip_and_prefix(ip, cidr)
165
- if cidr.to_s.empty?
166
- raise "Cidr is missing for IP '#{ip}'."
167
- elsif valid?(ip)
168
- raise "Ip address '#{ip}' is invalid."
169
- elsif !IPAddr.new(ip).private?
170
- raise "Ip Address #{ip} must be private."
171
- end
172
- end
173
-
174
- def validate_address_space(ip)
175
- if ip.split('/').size != 2
176
- raise "Cidr is invalid for IP #{ip}."
177
- elsif valid?(ip)
178
- raise "Address space '#{ip}' is invalid."
179
- end
180
- end
181
-
182
- def address_prefix(ip, cidr)
183
- ip + '/' + cidr.to_s
184
- end
185
-
186
- def valid?(ip)
187
- (IPAddr.new(ip) rescue nil).nil?
188
- end
189
- end
190
- end
@@ -51,11 +51,9 @@ module Azure
51
51
  storage_account.name = xml_content(
52
52
  storage_service_xml, 'ServiceName'
53
53
  )
54
-
55
54
  storage_service_properties = storage_service_xml.css(
56
55
  'StorageServiceProperties'
57
56
  )
58
-
59
57
  storage_account.description = xml_content(
60
58
  storage_service_properties, 'Description'
61
59
  )
@@ -77,6 +75,9 @@ module Azure
77
75
  storage_account.geo_replication_enabled = xml_content(
78
76
  storage_service_properties, 'GeoReplicationEnabled'
79
77
  )
78
+ storage_account.account_type = xml_content(
79
+ storage_service_properties, 'AccountType'
80
+ )
80
81
  storage_account.geo_primary_region = xml_content(
81
82
  storage_service_properties, 'GeoPrimaryRegion'
82
83
  )
@@ -112,7 +113,7 @@ module Azure
112
113
 
113
114
  def self.storage_update_to_xml(options)
114
115
  # Cannot update if options is nil or empty
115
- fail 'No options specified' if options.nil? || options.empty?
116
+ fail 'No options specified' if options.empty?
116
117
 
117
118
  # Either one of Label, or Description is required.
118
119
  if (options[:label].nil? || options[:label].empty?) &&
@@ -129,15 +130,13 @@ module Azure
129
130
  when :description, :label
130
131
  is_empty = value.nil? || value.empty?
131
132
  when :geo_replication_enabled
132
- is_empty = !(value.kind_of?(TrueClass)\
133
- || value.kind_of?(FalseClass))
133
+ is_empty = !(value.is_a?(TrueClass) || value.is_a?(FalseClass))
134
134
  when :extended_properties
135
135
  value.each do |p, v|
136
136
  is_empty = ((p.nil? || p.empty?) || (v.nil? || v.empty?))
137
137
  break unless is_empty
138
138
  end
139
139
  end
140
-
141
140
  break unless is_empty
142
141
  end
143
142
 
@@ -166,18 +165,16 @@ module Azure
166
165
  gre = options[:geo_replication_enabled]
167
166
  xml.GeoReplicationEnabled(
168
167
  gre
169
- ) unless gre.nil?\
170
- || !(gre.kind_of?(TrueClass) || gre.kind_of?(FalseClass))
168
+ ) unless gre.nil? || !(gre.is_a?(TrueClass) || gre.is_a?(FalseClass))
171
169
  xml.ExtendedProperties do
172
170
  options[:extended_properties].each do |name, value|
173
171
  xml.ExtendedProperty do
174
172
  xml.Name name
175
173
  xml.Value value
176
- end unless (name.nil? || name.empty?)\
177
- || (value.nil? || value.empty?)
174
+ end unless (name.to_s.empty?) || (value.to_s.empty?)
178
175
  end
179
- end unless options[:extended_properties].nil?\
180
- || options[:extended_properties].empty?
176
+ end unless options[:extended_properties].to_s.empty?
177
+ xml.AccountType options[:account_type] if options[:account_type]
181
178
  end
182
179
 
183
180
  def self.storage_account_keys_from_xml(storage_xml)
@@ -35,6 +35,7 @@ module Azure
35
35
  attr_accessor :status_of_secondary
36
36
  attr_accessor :creation_time
37
37
  attr_accessor :extended_properties
38
+ attr_accessor :account_type
38
39
  end
39
40
 
40
41
  # Represents Windows Azure storage account keys
@@ -38,20 +38,9 @@ module Azure
38
38
  #
39
39
  # * +name+ - String. Storage account name.
40
40
  #
41
- # Returns: A boolean value indicating whether the storage account exists.
42
- # If true, the storage account exists. If false, the storage account
43
- # does not exist.
41
+ # Returns an Azure::StorageManagement::StorageAccount instance
44
42
  def get_storage_account(name)
45
- return false if name.nil?
46
- flag = false
47
- storage_accounts = list_storage_accounts
48
- storage_accounts.each do |storage|
49
- if storage.name == name
50
- flag = true
51
- break
52
- end
53
- end
54
- flag
43
+ list_storage_accounts.select { |x| x.name.casecmp(name) == 0 }.first
55
44
  end
56
45
 
57
46
  # Public: Gets the properties of the storage account specified.
@@ -94,10 +83,14 @@ module Azure
94
83
  # * +:extended_properties+ - Hash. Key/Value pairs of extended
95
84
  # properties to add to the storage account. The key is used as the
96
85
  # property name and the value as its value. (optional)
86
+ # * +:account_type+ - String. Specifies the type of storage account
97
87
  #
88
+ # See http://msdn.microsoft.com/en-us/library/azure/hh264518.aspx
89
+ #
98
90
  # Returns None
99
91
  def create_storage_account(name, options = {})
100
92
  raise 'Name not specified' if !name || name.class != String || name.empty?
93
+ options[:account_type] ||= 'Standard_GRS'
101
94
  if get_storage_account(name)
102
95
  Loggerx.warn "Storage Account #{name} already exists. Skipped..."
103
96
  else
@@ -114,7 +107,7 @@ module Azure
114
107
  # ==== Attributes
115
108
  #
116
109
  # * +name+ - String. The name of the storage service.
117
- # * +options+ - Hash. Optional parameters.
110
+ # * +options+ - Hash. parameters.
118
111
  #
119
112
  # ==== Options
120
113
  #
@@ -126,14 +119,17 @@ module Azure
126
119
  # Required if no label is provided. If both label and description are
127
120
  # provided, only the label will get updated.
128
121
  # * +:geo_replication_enabled+ - Boolean (TrueClass/FalseClass). Boolean
129
- # flag indicating wheter to turn Geo replication on or off. (optional)
122
+ # flag indicating whether to turn Geo replication on or off. (optional)
130
123
  # * +:extended_properties+ - Hash. Key/Value pairs of extended
131
124
  # properties to add to the storage account. The key is used as the
132
125
  # property name and the value as its value. (optional)
126
+ # * +:account_type+ - String. Specifies the type of storage account
127
+ #
128
+ # See http://msdn.microsoft.com/en-us/library/azure/hh264516.aspx
133
129
  #
134
130
  # Returns None
135
131
  # Fails with RuntimeError if invalid options specified
136
- def update_storage_account(name, options = {})
132
+ def update_storage_account(name, options)
137
133
  if get_storage_account name
138
134
  Loggerx.info "Account '#{name}' exists, updating..."
139
135
  body = Serialization.storage_update_to_xml options
@@ -152,13 +148,15 @@ module Azure
152
148
  #
153
149
  # * +name+ - String. Storage account name.
154
150
  #
151
+ # See http://msdn.microsoft.com/en-us/library/azure/hh264517.aspx
152
+ #
155
153
  # Returns: None
156
154
  def delete_storage_account(name)
157
155
  Loggerx.info "Deleting Storage Account #{name}."
158
156
  request_path = "/services/storageservices/#{name}"
159
157
  request = ManagementHttpRequest.new(:delete, request_path)
160
158
  request.call
161
- rescue Exception => e
159
+ rescue => e
162
160
  e.message
163
161
  end
164
162
 
@@ -205,7 +203,6 @@ module Azure
205
203
  Loggerx.warn "Storage Account '#{name}' does not exist."
206
204
  end
207
205
  end
208
-
209
206
  end
210
207
  end
211
208
  end
@@ -17,7 +17,7 @@ module Azure
17
17
  class Version
18
18
  MAJOR = 0 unless defined? MAJOR
19
19
  MINOR = 6 unless defined? MINOR
20
- UPDATE = 6 unless defined? UPDATE
20
+ UPDATE = 7 unless defined? UPDATE
21
21
  PRE = nil unless defined? PRE
22
22
 
23
23
  class << self
@@ -33,13 +33,27 @@ module Azure
33
33
  os_images
34
34
  end
35
35
 
36
+ def self.virtual_machine_vmimages_from_xml(imageXML)
37
+ os_images = []
38
+ virtual_machine_images = imageXML.css('VMImages VMImage')
39
+ virtual_machine_images.each do |image_node|
40
+ image = VirtualMachineImage.new
41
+ image.os_type = xml_content(image_node, 'OS')
42
+ image.name = xml_content(image_node, 'Name')
43
+ image.category = xml_content(image_node, 'Category')
44
+ image.locations = xml_content(image_node, 'Location')
45
+ os_images << image
46
+ end
47
+ os_images
48
+ end
49
+
36
50
  def self.disks_from_xml(diskXML)
37
51
  os_disks = []
38
52
  disks = diskXML.css('Disks Disk')
39
53
  disks.each do |disk_node|
40
54
  disk = VirtualMachineDisk.new
41
55
  disk.name = xml_content(disk_node, 'Name')
42
- disk.os_type = xml_content(disk_node, 'OS')
56
+ disk.os_type = xml_content(disk_node, 'OSDiskConfiguration OS')
43
57
  disk.attached = !xml_content(disk_node, 'AttachedTo').empty?
44
58
  disk.image = xml_content(disk_node, 'SourceImageName')
45
59
  disk.size = xml_content(disk_node, 'LogicalDiskSizeInGB')
@@ -21,15 +21,44 @@ module Azure
21
21
  super()
22
22
  end
23
23
 
24
- # Public: Gets a list of virtual machine images from the server
24
+ # Public: Gets a list of all virtual machine images from the server both user created images and public images
25
+ # @param imageType = :public (public images), :private (user generated images). :all (both types)
26
+ # Returns an array of Azure::VirtualMachineImageManagementService objects
27
+ def list_virtual_machine_images(imageType=:all)
28
+ images = Array.new
29
+ if imageType == :public or imageType == :all
30
+ public_images = list_public_virtual_machine_images
31
+ images.concat public_images
32
+ end
33
+
34
+ if imageType == :private or imageType == :all
35
+ private_images = list_private_virtual_machine_images
36
+ images.concat private_images
37
+ end
38
+
39
+ images
40
+ end
41
+
42
+ # Public: Gets a list of virtual machine images from the server returns both user generated and public images by default
25
43
  #
26
44
  # Returns an array of Azure::VirtualMachineImageManagementService objects
27
- def list_virtual_machine_images
45
+ def list_public_virtual_machine_images
28
46
  request_path = '/services/images'
29
47
  request = ManagementHttpRequest.new(:get, request_path, nil)
30
48
  response = request.call
31
49
  Serialization.virtual_machine_images_from_xml(response)
32
50
  end
51
+
52
+ # Public: Gets a list of private virtual machine images from the server
53
+ #
54
+ # Returns an array of Azure::VirtualMachineImageManagementService objects
55
+ def list_private_virtual_machine_images
56
+ request_path = '/services/vmimages'
57
+ request = ManagementHttpRequest.new(:get, request_path, nil)
58
+ response = request.call
59
+ Serialization.virtual_machine_vmimages_from_xml(response)
60
+ end
61
+
33
62
  end
34
63
 
35
64
  class VirtualMachineDiskManagementService < BaseManagementService
@@ -183,7 +183,7 @@ module Azure
183
183
  def self.add_custom_data(xml, options)
184
184
  if options[:custom_data]
185
185
  custom_data = options[:custom_data]
186
- unless custom_data.chomp[/==$/]
186
+ unless custom_data.resembles_base64?
187
187
  custom_data = Base64.encode64(custom_data)
188
188
  end
189
189
  xml.CustomData custom_data
@@ -112,7 +112,7 @@ module Azure
112
112
  validate_deployment_params(params, options)
113
113
  options[:deployment_name] ||= options[:cloud_service_name]
114
114
  Loggerx.info 'Creating deploymnent...'
115
- options[:cloud_service_name] ||= generate_cloud_service_name(params[:vm_name])
115
+ options[:cloud_service_name] ||= generate_cloud_service_name(params[:vm_name])
116
116
  optionals = {}
117
117
  if options[:virtual_network_name]
118
118
  virtual_network_service = Azure::VirtualNetworkManagementService.new
@@ -122,7 +122,7 @@ module Azure
122
122
  else
123
123
  vnet = virtual_networks.first
124
124
  if !vnet.affinity_group.empty?
125
- options[:affinity_group_name] = vnet.affinity_group
125
+ optionals[:affinity_group_name] = vnet.affinity_group
126
126
  else
127
127
  optionals[:location] = vnet.location
128
128
  end
@@ -543,9 +543,9 @@ module Azure
543
543
  end
544
544
 
545
545
  def validate_role_size(vm_size)
546
- valid_role_sizes = %w(ExtraSmall Small Medium Large ExtraLarge A5 A6 A7 Basic_A0 Basic_A1 Basic_A2 Basic_A3 Basic_A4)
546
+ valid_role_sizes = %w(ExtraSmall Small Medium Large ExtraLarge A5 A6 A7 A8 A9 Basic_A0 Basic_A1 Basic_A2 Basic_A3 Basic_A4 Standard_D1 Standard_D2 Standard_D3 Standard_D4 Standard_D11 Standard_D12 Standard_D13 Standard_D14)
547
547
  if vm_size && !valid_role_sizes.include?(vm_size)
548
- Loggerx.error_with_exit "Value '#{vm_size}' specified for parameter 'vm_size' is invalid. Allowed values are 'ExtraSmall,Small,Medium,Large,ExtraLarge,A6,A7'"
548
+ Loggerx.error_with_exit "Value '#{vm_size}' specified for parameter 'vm_size' is invalid. Allowed values are 'ExtraSmall Small Medium Large ExtraLarge A5 A6 A7 A8 A9 Basic_A0 Basic_A1 Basic_A2 Basic_A3 Basic_A4 Standard_D1 Standard_D2 Standard_D3 Standard_D4 Standard_D11 Standard_D12 Standard_D13 Standard_D14'"
549
549
  end
550
550
  end
551
551