azurex 0.6.6 → 0.6.7

Sign up to get free protection for your applications and to get access to all the features.
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