avst-cloud 0.1.13 → 0.1.14

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