avst-cloud 0.1.13 → 0.1.14

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGU3ZWJiODcxNTczNjJhNGRkZGZlYmMxYTFkZjk0NDcyMzMzNTMyNA==
4
+ OGZhMjQwZjMyYjg1Y2I1OTQ4MWViOWZmZDNhOWZhZTMyOTEwYzBkYw==
5
5
  data.tar.gz: !binary |-
6
- Nzg1ODhhZGI5OTU2YTcyZTNjNDBmMzI1ZjgzOTRiNDY2ZjAzZWZmYQ==
6
+ NjUzMWY4MTg1ZDdhZWZhM2JiMjdhYTZiMDc3YjlhZWJkOTBiNzEyNw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MGIyMmI1ZGM4OTA1OWJkNjFmOWQ2ZmY4ZWY4MzVlYzJhMjRhNGU4OGJlNGRm
10
- YjgwZWRhZDAyMWVmNDUxZjhiMjc5YjAyZjcxNmE1ZTUzMGNlNzRiYmYzNDky
11
- MDMyYTVjYTlkYjI0ZDE3MWM1NGM1OTA5OGUyNWQzMGM4ZTdhODM=
9
+ NjRkZTQ4NmUwNjQxNzA2OWJkMTNiNGRmYTk0ZTQ0YzM0MzVmYjEyYjZjMDc5
10
+ Y2FhOTAwMmE2MTE5OGFlOWE4NzYzZjVhODJlOTQzZDUzYTMwMDhhNTVmYTE4
11
+ YjRkYjQ3MmI5N2NlNTY5MTczMDQ3OGQ4YjVkYmE0MzA4NDJjMTY=
12
12
  data.tar.gz: !binary |-
13
- MjI2NzA4MDM1ODExMGE3ZGIzZDNlOWI2OTQ2MDYwNzBkN2NjZTJjZmY2MzM3
14
- YWI3YWZlYTZkODkyNTUwOGY5YTcyNzJlOGUwZGUwMzFjOGMxZmMzZTkzOTYw
15
- ZTE2NGY1MjBhYTY4ZmIwNjRkNjVmYWIwOTZkMDk0NmJjZTdhMDk=
13
+ YzllYTEzYzgyYTcyOWVjOGFhMjA5YWM0MjVkZTRjZWQ1MzYyNTlmM2JiYzc4
14
+ ZjliY2ZjOTRiZmI2NzQ4YzlmYzM3OGZjODAyZDkwNmQ4ZTZiZTAwM2I4ODYx
15
+ OTk4MzBkZDhmYmExYzRlMDBmMzMxNTFkOWY2M2FmZjBjNzIzYTg=
data/README.md CHANGED
@@ -75,6 +75,10 @@ The application depends on several gems listed in avst-cloud.gemspec file. Bundl
75
75
 
76
76
  See bin/avst-cloud-azure for examples
77
77
 
78
+ ### Azure RM
79
+
80
+ Using new Azure Resource Manager way to manage resources. See bin/avst-cloud-azure-rm for examples
81
+
78
82
  ## Connecting to existing server
79
83
 
80
84
  ```
data/avst-cloud.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "avst-cloud"
7
- spec.version = '0.1.13'
7
+ spec.version = '0.1.14'
8
8
  spec.authors = ["Martin Brehovsky", "Jon Bevan", "Matthew Hope"]
9
9
  spec.email = ["mbrehovsky@adaptavist.com", "jbevan@adaptavist.com", "mhope@adaptavist.com"]
10
10
  spec.summary = %q{Automated creation, bootstrapping and provisioning of servers }
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = "http://www.adaptavist.com"
13
13
 
14
14
  spec.files = `git ls-files -z`.split("\x0")
15
- spec.executables = ["avst-cloud", "avst-cloud-puppet", "avst-cloud-rackspace", "avst-cloud-azure"]
15
+ spec.executables = ["avst-cloud", "avst-cloud-puppet", "avst-cloud-rackspace", "avst-cloud-azure", "avst-cloud-azure-rm"]
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ["lib"]
18
18
 
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "rake"
21
21
  spec.add_dependency "fog"
22
22
  spec.add_dependency "fog-azure"
23
+ spec.add_dependency "fog-azure-rm"
23
24
  spec.add_dependency "azure"
24
25
  spec.add_dependency "capistrano", "3.2.1"
25
26
  spec.add_dependency "capistrano-rvm"
data/bin/avst-cloud CHANGED
@@ -15,6 +15,8 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require 'avst-cloud'
18
+ require 'avst-cloud/aws_connection'
19
+ require 'avst-cloud/aws_server'
18
20
 
19
21
  avst_cloud_base="#{File.expand_path("../../", __FILE__)}"
20
22
 
@@ -71,7 +73,7 @@ post_upload_commands = [
71
73
  remote_server_debug = true
72
74
  debug_structured_log = false
73
75
 
74
- server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log)
76
+ server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log, false)
75
77
 
76
78
  git = "ssh://git@you_repo.git"
77
79
  branch = "master"
data/bin/avst-cloud-azure CHANGED
@@ -15,6 +15,8 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require 'avst-cloud'
18
+ require 'avst-cloud/azure_connection'
19
+ require 'avst-cloud/azure_server'
18
20
 
19
21
  avst_cloud_base="#{File.expand_path("../../", __FILE__)}"
20
22
 
@@ -35,6 +37,7 @@ instance_type = nil
35
37
  storage_account_name = nil
36
38
 
37
39
  conn.list_known_servers
40
+
38
41
  server = conn.create_server(server_name, user, private_key_file, location, image_id, instance_type, storage_account_name)
39
42
  # fog_server = conn.find_fog_server(server_name)
40
43
  # server = AvstCloud::AzureServer.new(fog_server, server_name, nil, user, private_key_file)
@@ -69,7 +72,7 @@ post_upload_commands = [
69
72
  remote_server_debug = true
70
73
  debug_structured_log = false
71
74
 
72
- server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log)
75
+ server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log, false)
73
76
 
74
77
  git = "ssh://git@you_repo.git"
75
78
  branch = "master"
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2015 Adaptavist.com Ltd.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'avst-cloud'
18
+ require 'avst-cloud/azure_rm_connection'
19
+ require 'avst-cloud/azure_rm_server'
20
+ avst_cloud_base="#{File.expand_path("../../", __FILE__)}"
21
+
22
+ # FILL IN YOUR AZURE ACCOUNT DETAILS
23
+ # See https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/
24
+ client_id = "" # Client ID:
25
+ client_secret = "" # 2 Year Key: ...
26
+ tenant_id = "" # Tenant ID: ...
27
+ subscription_id = "" # Subscription ID
28
+
29
+ # Initiate connector object
30
+ puts "Connection"
31
+
32
+ conn = AvstCloud::AzureRmConnection.new(client_id, client_secret, tenant_id, subscription_id)
33
+ # Lets create new Ubuntu 14 virtual machine
34
+ publisher = 'Canonical'
35
+ offer = 'UbuntuServer'
36
+ sku = '14.04.2-LTS'
37
+ version = 'latest'
38
+
39
+ server_name = "hostname1"
40
+ user = "ubuntu"
41
+ # Must comply to Azure pass guidelines
42
+ password = "superSecretUbuntuPass111_@"
43
+ location = nil # Will default to West Europe
44
+ resource_group = "new_resource_group" # if RG does not exists it will create it
45
+ vm_size = nil # Defaults to Basic_A0
46
+ storage_account_name = "new_storage_account" # creates it if not there
47
+ network_interface_name = "new_network_interface" # creates it if not there, see defaults in azure_rm_connection
48
+ virtual_network_name = "new_virtual_network" # creates it if not there, see defaults in azure_rm_connection
49
+ subnet_name = nil # by default one gets created for new new network, if there is one we use it if more or none it fails
50
+ ip_configuration_name = "new_ip_config" # creates it if not there, see defaults in azure_rm_connection
51
+ private_ip_allocation_method = "Dynamic"
52
+ public_ip_allocation_method = "Static"
53
+ subnet_address_list = nil
54
+ dns_list = nil
55
+ network_address_list = nil
56
+ address_prefix = nil
57
+ use_public_ip = true # will return public ip, if set to false, private will be used by bootstrap
58
+ serv = conn.create_server(server_name,
59
+ user,
60
+ password,
61
+ publisher,
62
+ offer,
63
+ sku,
64
+ version,
65
+ location,
66
+ resource_group,
67
+ vm_size,
68
+ storage_account_name,
69
+ network_interface_name,
70
+ virtual_network_name,
71
+ subnet_name,
72
+ ip_configuration_name,
73
+ private_ip_allocation_method,
74
+ public_ip_allocation_method,
75
+ subnet_address_list,
76
+ dns_list,
77
+ network_address_list,
78
+ address_prefix,
79
+ use_public_ip)
80
+
81
+ # serv = conn.server(server_name, resource_group ,user, password)
82
+ # puts serv.inspect
83
+ # serv.stop
84
+ # puts serv.inspect
85
+ # serv.start
86
+ # puts serv.inspect
87
+ # serv.destroy
88
+ # puts serv.inspect
89
+
90
+ pre_upload_commands = [
91
+ "echo 'pre_upload_command was here' >> /tmp/pre_upload",
92
+ ]
93
+
94
+ custom_file_uploads = {
95
+ "#{avst_cloud_base}/files/id_rsa" => "/tmp/.",
96
+ "#{avst_cloud_base}/files/known_hosts" => "/tmp/."
97
+ }
98
+
99
+ # Uploading ssh keys to access git repo in provisioning stage, make sure you provide correct keys
100
+ post_upload_commands = [
101
+ # "mkdir /home/#{user}/.ssh",
102
+ # "mv /tmp/id_rsa /home/#{user}/.ssh/.",
103
+ # "mv /tmp/known_hosts /home/#{user}/.ssh/.",
104
+ # "chmod 0600 /home/#{user}/.ssh/known_hosts",
105
+ # "chmod 0600 /home/#{user}/.ssh/id_rsa",
106
+ # "mkdir /var/opt/puppet",
107
+ # "chown #{user} /var/opt/puppet",
108
+ "apt-get update && apt-get install -o Dpkg::Options::='--force-confold' -f -y git puppet-common puppet",
109
+ "echo 'post_upload_command was here' >> /tmp/post_upload"
110
+ ]
111
+
112
+ remote_server_debug = true
113
+ debug_structured_log = false
114
+
115
+ serv.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log, true)
116
+
117
+ git = "ssh://git@you_repo.git"
118
+ branch = "master"
119
+ reference = nil # Tag
120
+ # In this example we do not use puppet-runner, check doco
121
+ puppet_runner = nil
122
+ puppet_runner_prepare = nil
123
+ custom_provisioning_commands = ["echo 'done' >> /tmp/done", "echo 'done' >> /tmp/done1"]
124
+ server_tmp_folder="/tmp/avst_cloud_tmp_#{Time.now.to_i}"
125
+
126
+ destination_folder = nil # defaults to /var/opt/puppet
127
+ serv.provision(git, branch, server_tmp_folder, reference, custom_provisioning_commands, puppet_runner, puppet_runner_prepare, destination_folder)
128
+
129
+ # serv.stop
130
+ # serv.start
131
+
132
+ custom_commands=nil
133
+ server_tmp_folder="/tmp/done"
134
+ serv.post_provisioning_cleanup(custom_commands, os, remote_server_debug, server_tmp_folder)
135
+ # serv.destroy
136
+
@@ -14,6 +14,8 @@
14
14
  # limitations under the License.
15
15
 
16
16
  require 'avst-cloud'
17
+ require 'avst-cloud/aws_connection'
18
+ require 'avst-cloud/aws_server'
17
19
 
18
20
  avst_cloud_base ="#{File.expand_path("../../", __FILE__)}"
19
21
 
@@ -148,7 +150,7 @@ post_upload_commands = [
148
150
  remote_server_debug = true
149
151
  debug_structured_log = false
150
152
 
151
- server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log)
153
+ server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log, false)
152
154
 
153
155
  server_tmp_folder = "/tmp/avst_cloud_tmp_#{Time.now.to_i}"
154
156
 
@@ -15,6 +15,8 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require 'avst-cloud'
18
+ require 'avst-cloud/rackspace_connection'
19
+ require 'avst-cloud/rackspace_server'
18
20
 
19
21
  avst_cloud_base="#{File.expand_path("../../", __FILE__)}"
20
22
 
@@ -59,7 +61,7 @@ post_upload_commands = [
59
61
  remote_server_debug = true
60
62
  debug_structured_log = false
61
63
 
62
- server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log)
64
+ server.bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log, false)
63
65
 
64
66
  git = "ssh://git@you_repo.git"
65
67
  branch = "master"
data/lib/avst-cloud.rb CHANGED
@@ -12,19 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require_relative './avst-cloud/aws_connection.rb'
16
- require_relative './avst-cloud/aws_server.rb'
17
- require_relative './avst-cloud/azure_connection.rb'
18
- require_relative './avst-cloud/azure_server.rb'
19
- require_relative './avst-cloud/rackspace_connection.rb'
20
- require_relative './avst-cloud/rackspace_server.rb'
21
- require_relative './avst-cloud/logging.rb'
22
- require 'fog'
23
15
  require 'net/ssh'
24
16
  require 'net/scp'
25
17
  require 'uri'
26
18
  require 'colorize'
27
-
19
+ require 'fog'
28
20
  module AvstCloud
29
-
30
21
  end
@@ -0,0 +1,515 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative './cloud_connection.rb'
16
+ require 'fog/azurerm'
17
+
18
+ module AvstCloud
19
+
20
+ class AzureRmConnection < AvstCloud::CloudConnection
21
+
22
+ attr_accessor :tenant_id, :subscription_id
23
+
24
+ def initialize(client_id, client_secret, tenant_id, subscription_id)
25
+ super('AzureRM', client_id, client_secret)
26
+ @tenant_id = tenant_id
27
+ @subscription_id = subscription_id
28
+ end
29
+
30
+ def server(server_name, resource_group, root_user, root_password, use_public_ip=true)
31
+ server = find_fog_server(server_name, resource_group)
32
+ if !root_user
33
+ root_user = get_root_user
34
+ end
35
+ ip_address = nil
36
+ if (server.network_interface_card_id)
37
+ network_interface_card_name = server.network_interface_card_id.split("/")[-1]
38
+ nic = connect_to_networks.network_interfaces(resource_group: resource_group).get(network_interface_card_name)
39
+ if nic
40
+ if use_public_ip
41
+ if nic.public_ip_address_id
42
+ ip_configuration_name = nic.public_ip_address_id.split("/")[-1]
43
+ pip = connect_to_networks.public_ips(resource_group: resource_group).get(ip_configuration_name)
44
+ ip_address = pip.ip_address
45
+ else
46
+ logger.debug "Can not find public ip for server #{server_name} in resource_group #{resource_group}"
47
+ raise "Can not find public ip"
48
+ end
49
+ else
50
+ ip_address = nic.private_ip_address
51
+ end
52
+ else
53
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
54
+ raise "Can not find network interface card"
55
+ end
56
+ else
57
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
58
+ raise "Can not find network interface card"
59
+ end
60
+
61
+ AvstCloud::AzureRmServer.new(server, server_name, ip_address, root_user, root_password)
62
+ end
63
+
64
+ def create_server(server_name,
65
+ user,
66
+ password,
67
+ publisher,
68
+ offer,
69
+ sku,
70
+ version,
71
+ location,
72
+ resource_group,
73
+ vm_size,
74
+ storage_account_name,
75
+ network_interface_name,
76
+ virtual_network_name,
77
+ subnet_name,
78
+ ip_configuration_name,
79
+ private_ip_allocation_method,
80
+ public_ip_allocation_method,
81
+ subnet_address_list,
82
+ dns_list,
83
+ network_address_list,
84
+ address_prefix,
85
+ use_public_ip)
86
+
87
+ location = location || 'West Europe'
88
+ user = user || get_root_user
89
+ vm_size = vm_size || "Basic_A0"
90
+
91
+ # Check that resource_group exists if not create one
92
+ check_create_resource_group(resource_group, location)
93
+
94
+ existing_server = find_fog_server(server_name, resource_group, false)
95
+
96
+ if existing_server
97
+ logger.error "Server #{server_name} found. #{existing_server.inspect}".yellow
98
+ raise "Running server with the same name found!"
99
+ else
100
+ logger.debug "Creating Azure server:"
101
+ logger.debug "Server name - #{server_name}"
102
+ logger.debug "location - #{location}"
103
+ logger.debug "storage_account_name - #{storage_account_name}"
104
+ logger.debug "vm_size - #{vm_size}"
105
+ logger.debug "user - #{user}"
106
+ logger.debug "password - #{password}"
107
+ logger.debug "publisher - #{publisher}"
108
+ logger.debug "offer - #{offer}"
109
+ logger.debug "sku - #{sku}"
110
+ logger.debug "version - #{version}"
111
+
112
+ # Check that storage_account exists if not create one
113
+ check_create_storage_account(storage_account_name, location, resource_group)
114
+
115
+ # Check if network_interface_card_id exists if not create one
116
+ # If not, create one for virtual network provided with subnet, security group and also public ip name
117
+ ip_address = check_create_network_interface(network_interface_name, resource_group, location, virtual_network_name, subnet_name, ip_configuration_name, private_ip_allocation_method, public_ip_allocation_method, subnet_address_list, dns_list, network_address_list, address_prefix, use_public_ip)
118
+
119
+ # create server
120
+ server = connect.servers.create(
121
+ name: server_name,
122
+ location: location,
123
+ resource_group: resource_group,
124
+ vm_size: vm_size,
125
+ storage_account_name: storage_account_name,
126
+ username: user,
127
+ password: password,
128
+ disable_password_authentication: false,
129
+ network_interface_card_id: "/subscriptions/#{@subscription_id}/resourceGroups/#{resource_group}/providers/Microsoft.Network/networkInterfaces/#{network_interface_name}",
130
+ publisher: publisher,
131
+ offer: offer,
132
+ sku: sku,
133
+ version: version
134
+ )
135
+
136
+ result_server = AvstCloud::AzureRmServer.new(server, server_name, ip_address, user, password)
137
+ logger.debug "[DONE]\n\n"
138
+ logger.debug "The server has been successfully created, to login onto the server:\n"
139
+ logger.debug "\t ssh #{user}@#{ip_address} with pass #{password} \n"
140
+ result_server
141
+ end
142
+ end
143
+
144
+ def list_storage_accounts(storage_account_name, resource_group)
145
+ storage_acc = connect_to_storages.storage_accounts(resource_group: resource_group)
146
+ .get(storage_account_name)
147
+ logger.debug "#{storage_acc.inspect}"
148
+ end
149
+
150
+ def check_create_network_interface(network_interface_name, resource_group, location, virtual_network_name, subnet_name, ip_configuration_name, private_ip_allocation_method="Dynamic", public_ip_allocation_method="Static", subnet_address_list=nil, dns_list=nil, network_address_list=nil, address_prefix=nil, use_public_ip=true)
151
+ nic = connect_to_networks.network_interfaces(resource_group: resource_group).get(network_interface_name)
152
+
153
+ # check/create ip_configuration_name exists
154
+ public_ip = check_create_ip_configuration(ip_configuration_name, resource_group, location, public_ip_allocation_method)
155
+ unless nic
156
+ # check/create virtual_network exists
157
+ vnet = check_create_virtual_network(virtual_network_name, resource_group, location, subnet_address_list, dns_list, network_address_list)
158
+
159
+ # check if provided subnet exists, if nil then use default one
160
+ unless subnet_name
161
+ subnets = connect_to_networks.subnets(resource_group: resource_group, virtual_network_name: virtual_network_name)
162
+ if subnets.length == 0
163
+ raise "Can not decide what subnet to choose. There are no subnets for virtual network #{virtual_network_name}."
164
+ elsif subnets.length != 1
165
+ raise "Can not decide what subnet to choose. Please specify subnet name."
166
+ end
167
+ subnet_name = subnets[0].name
168
+ logger.debug "Using subnet #{subnet_name}"
169
+ end
170
+
171
+ nic = connect_to_networks.network_interfaces.create(
172
+ name: network_interface_name,
173
+ resource_group: resource_group,
174
+ location: location,
175
+ subnet_id: "/subscriptions/#{@subscription_id}/resourceGroups/#{resource_group}/providers/Microsoft.Network/virtualNetworks/#{virtual_network_name}/subnets/#{subnet_name}",
176
+ public_ip_address_id: "/subscriptions/#{@subscription_id}/resourceGroups/#{resource_group}/providers/Microsoft.Network/publicIPAddresses/#{ip_configuration_name}",
177
+ ip_configuration_name: ip_configuration_name,
178
+ private_ip_allocation_method: private_ip_allocation_method
179
+ )
180
+ end
181
+ if use_public_ip
182
+ public_ip
183
+ else
184
+ nic.private_ip_address
185
+ end
186
+ end
187
+
188
+ def find_network_interface_for_server(server_name, resource_group, should_fail=false)
189
+ server = find_fog_server(server_name, resource_group)
190
+ network_interface = nil
191
+ if (server and server.network_interface_card_id)
192
+ network_interface_card_name = server.network_interface_card_id.split("/")[-1]
193
+ network_interface = connect_to_networks.network_interfaces(resource_group: resource_group).get(network_interface_card_name)
194
+ else
195
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
196
+ raise "Can not find network interface card" if should_fail
197
+ end
198
+ network_interface
199
+ end
200
+
201
+ def destroy_network_interface(network_interface_name, resource_group)
202
+ logger.debug "Deleting #{network_interface_name}"
203
+ network_interface = connect_to_networks.network_interfaces(resource_group: resource_group).get(network_interface_name)
204
+ if network_interface
205
+ network_interface.destroy
206
+ end
207
+ logger.debug "Network interface deleted"
208
+ end
209
+
210
+ def destroy_network_interface_for_server(server_name, resource_group, should_fail=false)
211
+ server = find_fog_server(server_name, resource_group)
212
+ if (server.network_interface_card_id)
213
+ network_interface_card_name = server.network_interface_card_id.split("/")[-1]
214
+ destroy_network_interface(network_interface_card_name, resource_group)
215
+ else
216
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
217
+ raise "Can not find network interface card" if should_fail
218
+ end
219
+ end
220
+
221
+ def check_create_ip_configuration(ip_configuration_name, resource_group, location, public_ip_allocation_method="Static")
222
+ ip_configuration = connect_to_networks.public_ips(resource_group: resource_group).get(ip_configuration_name)
223
+ unless ip_configuration
224
+ ip_configuration = connect_to_networks.public_ips.create(
225
+ name: ip_configuration_name,
226
+ resource_group: resource_group,
227
+ location: location,
228
+ public_ip_allocation_method: public_ip_allocation_method
229
+ )
230
+ end
231
+ ip_configuration.ip_address
232
+ end
233
+
234
+ def destroy_ip_configuration(ip_configuration_name, resource_group)
235
+ logger.debug "Deleting #{ip_configuration_name}"
236
+ public_ip = connect_to_networks.public_ips(resource_group: resource_group).get(ip_configuration_name)
237
+ if public_ip
238
+ public_ip.destroy
239
+ end
240
+ logger.debug "Public IP deleted"
241
+ end
242
+
243
+ def destroy_ip_configuration_for_server(server_name, resource_group, should_fail=false)
244
+ server = find_fog_server(server_name, resource_group)
245
+ if (server.network_interface_card_id)
246
+ network_interface_card_name = server.network_interface_card_id.split("/")[-1]
247
+ nic = connect_to_networks.network_interfaces(resource_group: resource_group).get(network_interface_card_name)
248
+ if nic
249
+ if nic.public_ip_address_id
250
+ ip_configuration_name = nic.public_ip_address_id.split("/")[-1]
251
+ destroy_ip_configuration(ip_configuration_name, resource_group)
252
+ else
253
+ logger.debug "Can not find public ip for server #{server_name} in resource_group #{resource_group}"
254
+ raise "Can not find public ip" if should_fail
255
+ end
256
+ else
257
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
258
+ raise "Can not find network interface card" if should_fail
259
+ end
260
+ else
261
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
262
+ raise "Can not find network interface card" if should_fail
263
+ end
264
+ end
265
+
266
+ def check_create_subnet(subnet_name, resource_group, location, virtual_network_name, address_prefix=nil, subnet_address_list=nil, dns_list=nil, network_address_list=nil)
267
+ subnet = connect_to_networks.subnets(resource_group: resource_group, virtual_network_name: virtual_network_name).get(subnet_name)
268
+ unless subnet
269
+ logger.debug "Subnet #{subnet_name} not found, creating new one"
270
+ address_prefix = address_prefix || '10.1.0.0/24'
271
+ subnet = connect_to_networks.subnets.create(
272
+ name: subnet_name,
273
+ resource_group: resource_group,
274
+ virtual_network_name: virtual_network_name,
275
+ address_prefix: address_prefix
276
+ )
277
+ end
278
+ end
279
+
280
+ def destroy_subnet(subnet_name, resource_group, virtual_network_name)
281
+ logger.debug "Deleting #{subnet_name}"
282
+ subnet = connect_to_networks.subnets(resource_group: resource_group, virtual_network_name: virtual_network_name).get(subnet_name)
283
+ if subnet
284
+ subnet.destroy
285
+ end
286
+ logger.debug "Subnet deleted"
287
+ end
288
+
289
+ def destroy_subnet_for_server(server_name, resource_group, should_fail=false)
290
+ server = find_fog_server(server_name, resource_group)
291
+ if (server.network_interface_card_id)
292
+ network_interface_card_name = server.network_interface_card_id.split("/")[-1]
293
+ nic = connect_to_networks.network_interfaces(resource_group: resource_group).get(network_interface_card_name)
294
+ if nic
295
+ if nic.subnet_id
296
+ subnet_id_name = nic.subnet_id.split("/")[-1]
297
+ virtual_network_name = nic.subnet_id.split("virtualNetworks/")[-1].split("/")[0]
298
+ destroy_subnet(subnet_id_name, resource_group, virtual_network_name)
299
+ else
300
+ logger.debug "Can not find subnet for server #{server_name} in resource_group #{resource_group}"
301
+ raise "Can not find subnet" if should_fail
302
+ end
303
+ else
304
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
305
+ raise "Can not find network interface card" if should_fail
306
+ end
307
+ else
308
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
309
+ raise "Can not find network interface card" if should_fail
310
+ end
311
+ end
312
+
313
+ def check_create_virtual_network(virtual_network_name, resource_group, location, subnet_address_list=nil, dns_list=nil, network_address_list=nil)
314
+ vnet = connect_to_networks.virtual_networks(resource_group: resource_group).get(virtual_network_name)
315
+ # virtual_networks.get(virtual_network_name, resource_group)
316
+ unless vnet
317
+ logger.debug "Virtual network #{virtual_network_name} not found, creating new one"
318
+ subnet_address_list = subnet_address_list || '10.1.0.0/24'
319
+ dns_list = dns_list || '8.8.8.8,8.8.4.4,10.1.0.5,10.1.0.6'
320
+ network_address_list = network_address_list || '10.1.0.0/16,10.2.0.0/16'
321
+ vnet = connect_to_networks.virtual_networks.create(
322
+ name: virtual_network_name,
323
+ location: location,
324
+ resource_group: resource_group,
325
+ subnet_address_list: subnet_address_list,
326
+ dns_list: dns_list,
327
+ network_address_list: network_address_list
328
+ )
329
+ end
330
+ vnet
331
+ end
332
+
333
+ def destroy_virtual_network_for_server(server_name, resource_group, should_fail=false)
334
+ server = find_fog_server(server_name, resource_group)
335
+ if (server.network_interface_card_id)
336
+ network_interface_card_name = server.network_interface_card_id.split("/")[-1]
337
+ nic = connect_to_networks.network_interfaces(resource_group: resource_group).get(network_interface_card_name)
338
+ if nic
339
+ if nic.subnet_id
340
+ virtual_network_name = nic.subnet_id.split("virtualNetworks/")[-1].split("/")[0]
341
+ destroy_virtual_network(virtual_network_name, resource_group)
342
+ else
343
+ logger.debug "Can not find virtual network for server #{server_name} in resource_group #{resource_group}"
344
+ raise "Can not find subnet" if should_fail
345
+ end
346
+ else
347
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
348
+ raise "Can not find network interface card" if should_fail
349
+ end
350
+ else
351
+ logger.debug "Can not find network interface card for server #{server_name} in resource_group #{resource_group}"
352
+ raise "Can not find network interface card" if should_fail
353
+ end
354
+ end
355
+
356
+ def destroy_virtual_network(virtual_network_name, resource_group)
357
+ logger.debug "Deleting #{virtual_network_name}"
358
+ vnet = connect_to_networks.virtual_networks(resource_group: resource_group).get(virtual_network_name)
359
+ if vnet
360
+ vnet.destroy
361
+ end
362
+ logger.debug "Virtual network deleted"
363
+ end
364
+
365
+ def check_create_storage_account(storage_account_name, location, resource_group)
366
+ account = connect_to_storages.storage_accounts(resource_group: resource_group).get(storage_account_name)
367
+ unless account
368
+ logger.debug "Storage account #{storage_account_name} not found, creating new one"
369
+ account = connect_to_storages.storage_accounts.create(
370
+ name: storage_account_name,
371
+ location: location,
372
+ resource_group: resource_group
373
+ )
374
+ end
375
+ account
376
+ end
377
+
378
+ def find_storage_account_name_for_server(server_name, resource_group, should_fail=false)
379
+ server = find_fog_server(server_name, resource_group)
380
+ storage_account_name = nil
381
+ if (server and server.storage_account_name)
382
+ storage_account_name = server.storage_account_name
383
+ end
384
+ storage_account_name
385
+ end
386
+
387
+ def destroy_storage_account_for_server(server_name, resource_group, should_fail=false)
388
+ server = find_fog_server(server_name, resource_group)
389
+ if (server.storage_account_name)
390
+ storage_account_name = server.storage_account_name
391
+ destroy_storage_account(storage_account_name, resource_group)
392
+ else
393
+ logger.debug "Can not find storage account for server #{server_name} in resource_group #{resource_group}"
394
+ raise "Can not find storage account" if should_fail
395
+ end
396
+ end
397
+
398
+ def destroy_storage_account(storage_account_name, resource_group)
399
+ logger.debug "Deleting #{storage_account_name}"
400
+ account = connect_to_storages.storage_accounts(resource_group: resource_group).get(storage_account_name)
401
+ if account
402
+ account.destroy
403
+ end
404
+ logger.debug "Storage deleted"
405
+ end
406
+
407
+ def check_create_resource_group(resource_group, location)
408
+ logger.debug "Searching for #{resource_group}"
409
+ found_resource_group = connect_to_resources.resource_groups.get(resource_group)
410
+ unless found_resource_group
411
+ logger.debug "Resource group #{resource_group} not found, creating new one"
412
+ found_resource_group = connect_to_resources.resource_groups.create(
413
+ name: resource_group,
414
+ location: location
415
+ )
416
+ end
417
+ found_resource_group
418
+ end
419
+
420
+ def destroy_resource_group(resource_group)
421
+ logger.debug "Deleting #{resource_group}"
422
+ found_resource_group = connect_to_resources.resource_groups.get(resource_group)
423
+ if found_resource_group
424
+ found_resource_group.destroy
425
+ end
426
+ end
427
+
428
+ def server_status(server_name, resource_group)
429
+ connect.servers(resource_group: resource_group).get(server_name).vm_status
430
+ end
431
+
432
+ def list_images
433
+ connect.images.each do |im|
434
+ logger.debug im.inspect
435
+ end
436
+ end
437
+
438
+ # Returns list of servers from fog
439
+ def list_known_servers(resource_group)
440
+ connect.servers(resource_group: resource_group).each do |sr|
441
+ logger.debug sr.inspect
442
+ end
443
+ end
444
+
445
+ def find_fog_server(server_name, resource_group, should_fail=true)
446
+ serv = connect.servers(resource_group: resource_group).get(server_name)
447
+ unless serv
448
+ if should_fail
449
+ logger.debug "Server not found for name: #{server_name} in resource group #{resource_group}"
450
+ raise "Server not found for name: #{server_name} in resource group #{resource_group}"
451
+ end
452
+ end
453
+ serv
454
+ end
455
+
456
+ private
457
+ def get_root_user
458
+ "azureuser"
459
+ end
460
+ def connect
461
+ unless @connection
462
+ logger.debug "Creating new connection to Azure"
463
+
464
+ @connection = Fog::Compute.new(
465
+ provider: 'AzureRM',
466
+ tenant_id: @tenant_id,
467
+ client_id: @provider_access_user,
468
+ client_secret: @provider_access_pass,
469
+ subscription_id: @subscription_id
470
+ )
471
+ end
472
+ @connection
473
+ end
474
+
475
+ def connect_to_networks
476
+ unless @networks_connection
477
+ logger.debug "Creating new connection to Azure networks"
478
+ @networks_connection = Fog::Network::AzureRM.new(
479
+ tenant_id: @tenant_id,
480
+ client_id: @provider_access_user,
481
+ client_secret: @provider_access_pass,
482
+ subscription_id: @subscription_id
483
+ )
484
+ end
485
+ @networks_connection
486
+ end
487
+
488
+ def connect_to_storages
489
+ unless @storage_connection
490
+ logger.debug "Creating new connection to Azure storage accounts"
491
+ @storage_connection = Fog::Storage.new(
492
+ provider: 'AzureRM',
493
+ tenant_id: @tenant_id,
494
+ client_id: @provider_access_user,
495
+ client_secret: @provider_access_pass,
496
+ subscription_id: @subscription_id
497
+ )
498
+ end
499
+ @storage_connection
500
+ end
501
+
502
+ def connect_to_resources
503
+ unless @resources_connection
504
+ logger.debug "Creating new connection to Azure resources"
505
+ @resources_connection = Fog::Resources::AzureRM.new(
506
+ tenant_id: @tenant_id,
507
+ client_id: @provider_access_user,
508
+ client_secret: @provider_access_pass,
509
+ subscription_id: @subscription_id
510
+ )
511
+ end
512
+ @resources_connection
513
+ end
514
+ end
515
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright 2015 Adaptavist.com Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative './cloud_server.rb'
16
+
17
+ module AvstCloud
18
+ class AzureRmServer < AvstCloud::CloudServer
19
+
20
+ def stop
21
+ if @server
22
+ logger.debug "Stopping #{@server_name}"
23
+ @server.power_off
24
+ logger.debug "[DONE]\n\n"
25
+ logger.debug "Server #{@server_name} stopped...".green
26
+ else
27
+ raise "Server #{@server_name} does not exist!".red
28
+ end
29
+ end
30
+
31
+ def start
32
+ if @server
33
+ logger.debug "Starting #{@server_name}"
34
+ @server.start
35
+ logger.debug "[DONE]\n\n"
36
+ logger.debug "Server #{@server_name} started...".green
37
+ else
38
+ raise "Server #{@server_name} does not exist!".red
39
+ end
40
+ end
41
+
42
+ def destroy
43
+ if @server
44
+ logger.debug "Killing #{@server_name}"
45
+ @server.destroy
46
+ logger.debug "Server #{@server_name} destroyed...".green
47
+ else
48
+ raise "Server #{@server_name} does not exist!".red
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -28,10 +28,10 @@ module AvstCloud
28
28
  @access_password = access_password
29
29
  end
30
30
 
31
- def bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log)
31
+ def bootstrap(pre_upload_commands, custom_file_uploads, post_upload_commands, remote_server_debug, debug_structured_log, enable_sudo="false")
32
32
  logger.debug "Bootstrapping #{server_name}...".green
33
33
  run_tasks([AvstCloud::WaitUntilReady.new])
34
- disable_tty_task = AvstCloud::DisableRequireTty.new(@access_user)
34
+ disable_tty_task = AvstCloud::DisableRequireTty.new(@access_user, @access_password, enable_sudo)
35
35
  pre_upload_commands_tasks = AvstCloud::SshCommandTask.new(pre_upload_commands, remote_server_debug, debug_structured_log)
36
36
  custom_file_uploads_tasks = AvstCloud::ScpTask.new(custom_file_uploads)
37
37
  post_upload_commands_tasks = AvstCloud::SshCommandTask.new(post_upload_commands, remote_server_debug, debug_structured_log)
@@ -105,32 +105,50 @@ module AvstCloud
105
105
 
106
106
  # In case Requiretty is set in sudoers disable it for bootstrapping and provisioning
107
107
  # for user that performs it
108
+ # In case user does not have sudo no pass, enable it for bootstrapping and provisioning
108
109
  class DisableRequireTty < AvstCloud::SshTask
109
110
  include Logging
110
- def initialize(for_user)
111
+ def initialize(for_user, pass, enable_passwordless_sudo=false)
111
112
  @for_user = for_user
113
+ @user_password = pass
114
+ @enable_passwordless_sudo = enable_passwordless_sudo
112
115
  end
113
116
  def ssh_command(session)
117
+ commands = []
118
+ if @enable_passwordless_sudo
119
+ commands << "sudo su -c 'echo \"#{@for_user} ALL=(ALL) NOPASSWD: ALL\" > /etc/sudoers.d/zzz_#{@for_user}'"
120
+ redirect_type = ">>"
121
+ else
122
+ redirect_type = ">"
123
+ end
124
+
125
+ commands << "sudo su -c 'echo \"Defaults:#{@for_user} !requiretty\" #{redirect_type} /etc/sudoers.d/zzz_#{@for_user}'"
126
+
114
127
  session.open_channel do |channel|
115
128
  channel.request_pty do |ch, success|
116
129
  raise 'Error requesting pty' unless success
130
+ end
131
+ channel.exec(commands.join(';')) do |ch, success|
132
+ abort "Could not execute commands!" unless success
117
133
 
118
- ch.send_channel_request('shell') do |ch, success|
119
- raise 'Error opening shell' unless success
134
+ channel.on_data do |ch, data|
135
+ if @debug
136
+ STDOUT.print "#{data}"
137
+ end
138
+ channel.send_data "#{@user_password}\n" if data =~ /password/
120
139
  end
121
- end
122
- channel.on_data do |ch, data|
123
- if @debug
124
- STDOUT.print data
140
+ channel.on_extended_data do |ch, type, data|
141
+ STDOUT.print "stderr: #{data}"
142
+ end
143
+
144
+ channel.on_close do |ch|
145
+ if @debug
146
+ STDOUT.print "Channel is closing!"
147
+ end
125
148
  end
126
149
  end
127
- channel.on_extended_data do |ch, type, data|
128
- STDOUT.print "Error: #{data}\n"
129
- end
130
- channel.send_data("sudo su -c 'echo 'Defaults:#{@for_user}\\ \\!requiretty' >> /etc/sudoers'\n")
131
- channel.send_data("exit\n")
132
- session.loop
133
150
  end
151
+ session.loop
134
152
  end
135
153
  end
136
154
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avst-cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Brehovsky
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-04-15 00:00:00.000000000 Z
13
+ date: 2016-06-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -68,6 +68,20 @@ dependencies:
68
68
  - - ! '>='
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: fog-azure-rm
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'
71
85
  - !ruby/object:Gem::Dependency
72
86
  name: azure
73
87
  requirement: !ruby/object:Gem::Requirement
@@ -190,6 +204,7 @@ executables:
190
204
  - avst-cloud-puppet
191
205
  - avst-cloud-rackspace
192
206
  - avst-cloud-azure
207
+ - avst-cloud-azure-rm
193
208
  extensions: []
194
209
  extra_rdoc_files: []
195
210
  files:
@@ -202,6 +217,7 @@ files:
202
217
  - avst-cloud.gemspec
203
218
  - bin/avst-cloud
204
219
  - bin/avst-cloud-azure
220
+ - bin/avst-cloud-azure-rm
205
221
  - bin/avst-cloud-puppet
206
222
  - bin/avst-cloud-rackspace
207
223
  - config/custom_system_config/hiera-configs/defaults/example.yaml
@@ -214,6 +230,8 @@ files:
214
230
  - lib/avst-cloud/aws_connection.rb
215
231
  - lib/avst-cloud/aws_server.rb
216
232
  - lib/avst-cloud/azure_connection.rb
233
+ - lib/avst-cloud/azure_rm_connection.rb
234
+ - lib/avst-cloud/azure_rm_server.rb
217
235
  - lib/avst-cloud/azure_server.rb
218
236
  - lib/avst-cloud/cloud_connection.rb
219
237
  - lib/avst-cloud/cloud_server.rb