vagrant-1cloud 1.0.7 → 1.0.8

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: adfa2a049e94d0793791807f1772dfd593616ea4
4
- data.tar.gz: 5b184e38522777d486a70827bf9e1874b3f00be7
3
+ metadata.gz: f6b158d2a5ebd6ba2844225d9b1b8a5f01e30a36
4
+ data.tar.gz: 579da12b738510cdb4ec94000480543108f5c130
5
5
  SHA512:
6
- metadata.gz: 682e2dcb1ea3e8d42444e5916f2e75b95e309a22407a293a0b34c726aee74cf82a3270f9adabb446d02e928e43d9f49769dea14754cf8bbb0a455b50c81a17be
7
- data.tar.gz: de6930ee66c9f7c4aed590f3f38df5a041d56a7e01791c651ce124e406248f4c6d7063216b72015afd4b5df3d965485e448fd5e69c2d5695d3f4eb2c672d8b68
6
+ metadata.gz: cb6b3ab49082434521372f91dbc3aaecffbee9840537cd095b10712d748d9ab042e89e5ddc6418d3d0b94b766e27df6288dd52339e99250a56538f5953b115db
7
+ data.tar.gz: 5ebf0e8bafad0d97d9e741cb51f7171be1337c6facaacb75e46afc148e488f1e91c516fa707d8450736ffc3232e6c098cbd8090dc8a4325c9e7600bda6b1ab36
data/.gitignore CHANGED
@@ -10,4 +10,4 @@
10
10
  vagrant-1cloud.iml
11
11
  /.idea/
12
12
  /.svn/
13
- .rake_tasks~
13
+ .rake_tasks~
@@ -0,0 +1,115 @@
1
+ 1cloud Vagrant Provider
2
+ ==============================
3
+
4
+ [![Gem](https://img.shields.io/gem/v/vagrant-1cloud.svg)](https://rubygems.org/gems/vagrant-1cloud)
5
+
6
+ `vagrant-1cloud` is a Vagrant provider plugin that supports the management of [1cloud](https://1cloud.ru) VPS.
7
+
8
+ Features include:
9
+ - Create and destroy VPS
10
+ - Power on and off VPS
11
+ - Provision a VPS with shell
12
+ - Setup a SSH public key for authentication
13
+ - Create a new user account during VPS creation
14
+ - Create private network
15
+ - Rebuild VPS
16
+
17
+
18
+ Install
19
+ -------
20
+ Install the provider plugin using the Vagrant command-line interface:
21
+
22
+ `vagrant plugin install vagrant-1cloud`
23
+
24
+
25
+ Configure
26
+ ---------
27
+ Once the provider has been installed, you will need to configure your project to use it. See the following example for a basic multi-machine `Vagrantfile` implementation that manages two 1cloud VPS:
28
+
29
+ ```ruby
30
+ Vagrant.configure('2') do |config|
31
+
32
+ config.vm.define "vps1" do |config|
33
+ config.vm.provider :onecloud do |provider, override|
34
+ override.ssh.private_key_path = '~/.ssh/id_rsa'
35
+ override.vm.box = 'onecloud'
36
+ provider.token = 'YOUR TOKEN'
37
+ end
38
+ end
39
+
40
+ config.vm.define "vps2" do |config|
41
+ config.vm.provider :onecloud do |provider, override|
42
+ override.ssh.private_key_path = '~/.ssh/id_rsa'
43
+ override.vm.box = 'onecloud'
44
+ provider.token = 'YOUR TOKEN'
45
+ end
46
+ end
47
+
48
+ end
49
+ ```
50
+
51
+ **Configuration Requirements**
52
+ - You *must* specify the `override.ssh.private_key_path` to enable authentication with the VPS.
53
+ - You *must* specify your 1cloud Personal Access Token at `provider.token`.
54
+
55
+ **Supported Configuration Attributes**
56
+ The following attributes are available to further configure the provider:
57
+ - `provider.image`
58
+ * A string representing the image ID to use when creating a new VPS. It defaults to `7` (ubuntu-14-04-x64).
59
+ - `provider.region`
60
+ * A string representing the region to create the new VPS in. It defaults to `SdnSpb`.
61
+ - `provider.hdd`
62
+ * A number representing the disk space (in GB) to use when creating a new VPS (e.g. 50). It defaults to 10.
63
+ - `provider.hdd_type`
64
+ * A string representing the disk type to use when creating a new VPS (e.g. `SSD`). It defaults to `SAS`.
65
+ - `provider.cpu`
66
+ * A number representing the amount of cores to use when creating a new VPS (e.g. 2). It defaults to 1.
67
+ - `provider.ram`
68
+ * A number representing the RAM (in MB) to use when creating a new VPS (e.g. 1024). It defaults to 512.
69
+ - `provider.hi_perf`
70
+ * A boolean flag indicating whether to use high performance pool or not. It defaults to `false`.
71
+ - `provider.private_net`
72
+ * A hash representing the pair that indicates the private network name and IP address of a new VPS (e.g. {"testnet" => "192.168.1.10"} or {"testnet" => nil} to set IP address automatically). VPS isn't added to private network by default.
73
+ - `config.vm.synced_folder`
74
+ * Supports both rsync__args and rsync__exclude, see the [Vagrant Docs](http://docs.vagrantup.com/v2/synced-folders/rsync.html) for more information. rsync__args default to `["--verbose", "--archive", "--delete", "-z", "--copy-links"]` and rsync__exclude defaults to `[".vagrant/"]`.
75
+
76
+ The provider will create a new user account with the specified SSH key for authorization if `config.ssh.username` is set.
77
+
78
+
79
+ Run
80
+ ---
81
+ After creating your project's `Vagrantfile` with the required configuration
82
+ attributes described above, you may create a new VPS with the following
83
+ command:
84
+
85
+ $ vagrant up --provider=onecloud
86
+
87
+ This command will create a new VPS, setup your SSH key for authentication,
88
+ create a new user account, and run the provisioners you have configured.
89
+
90
+ **Supported Commands**
91
+
92
+ The provider supports the following Vagrant sub-commands:
93
+ - `vagrant destroy` - Destroys the VPS instance.
94
+ - `vagrant ssh` - Logs into the VPS instance using the configured user account.
95
+ - `vagrant halt` - Powers off the VPS instance.
96
+ - `vagrant provision` - Runs the configured provisioners and rsyncs any specified `config.vm.synced_folder`.
97
+ - `vagrant reload` - Reboots the VPS instance.
98
+ - `vagrant status` - Outputs the status (active, off, not created) for the VPS instance.
99
+ - `vagrant create-network` - Creates private network.
100
+ - `vagrant rebuild` - Rebuilds the VPS.
101
+
102
+ Troubleshooting
103
+ ---------------
104
+ Before submitting a GitHub issue, please ensure both Vagrant and vagrant-onecloud are fully up-to-date.
105
+ * For the latest Vagrant version, please visit the [Vagrant](https://www.vagrantup.com/) website
106
+ * To update Vagrant plugins, run the following command: `vagrant plugin update`
107
+
108
+ * `vagrant plugin install vagrant-onecloud`
109
+ * Installation on OS X may not working due to a SSL certificate problem, and you may need to specify a certificate path explicitly. To do so, run `ruby -ropenssl -e "p OpenSSL::X509::DEFAULT_CERT_FILE"`. Then, add the following environment variable to your `.bash_profile` script and `source` it: `export SSL_CERT_FILE=/usr/local/etc/openssl/cert.pem`.
110
+
111
+
112
+ FAQ
113
+ ---
114
+
115
+ * The Chef provisioner is no longer supported by default. Please use the `vagrant-omnibus` plugin to install Chef on Vagrant-managed machines. This plugin provides control over the specific version of Chef to install.
@@ -8,6 +8,9 @@ require 'vagrant-1cloud/actions/reload'
8
8
  require 'vagrant-1cloud/actions/setup_user'
9
9
  require 'vagrant-1cloud/actions/modify_provision_path'
10
10
  require 'vagrant-1cloud/actions/private_network'
11
+ require 'vagrant-1cloud/actions/rebuild'
12
+ require 'vagrant-1cloud/actions/setup_sudo'
13
+ require 'vagrant-1cloud/actions/setup_key'
11
14
 
12
15
  module VagrantPlugins
13
16
  module OneCloud
@@ -49,6 +52,22 @@ module VagrantPlugins
49
52
  end
50
53
  end
51
54
 
55
+ def self.ssh_run
56
+ return Vagrant::Action::Builder.new.tap do |builder|
57
+ builder.use ConfigValidate
58
+ builder.use Call, CheckState do |env, b|
59
+ case env[:machine_state]
60
+ when :Active
61
+ b.use SSHRun
62
+ when :off
63
+ env[:ui].info I18n.t('vagrant_1cloud.info.off')
64
+ when :not_created
65
+ env[:ui].info I18n.t('vagrant_1cloud.info.not_created')
66
+ end
67
+ end
68
+ end
69
+ end
70
+
52
71
  def self.provision
53
72
  return Vagrant::Action::Builder.new.tap do |builder|
54
73
  builder.use ConfigValidate
@@ -78,8 +97,10 @@ module VagrantPlugins
78
97
  b.use PowerOn
79
98
  b.use provision
80
99
  when :not_created
100
+ b.use SetupKey
81
101
  b.use Create
82
102
  b.use PrivateNetwork
103
+ b.use SetupSudo
83
104
  b.use SetupUser
84
105
  b.use provision
85
106
  end
@@ -123,6 +144,24 @@ module VagrantPlugins
123
144
  end
124
145
  end
125
146
  end
147
+
148
+ def self.rebuild
149
+ return Vagrant::Action::Builder.new.tap do |builder|
150
+ builder.use ConfigValidate
151
+ builder.use Call, CheckState do |env, b|
152
+ case env[:machine_state]
153
+ when :Active, :off
154
+ b.use Rebuild
155
+ b.use PrivateNetwork
156
+ b.use SetupSudo
157
+ b.use SetupUser
158
+ b.use provision
159
+ when :not_created
160
+ env[:ui].info I18n.t('vagrant_1cloud.info.not_created')
161
+ end
162
+ end
163
+ end
164
+ end
126
165
  end
127
166
  end
128
167
  end
@@ -1,5 +1,4 @@
1
1
  require 'vagrant-1cloud/helpers/client'
2
- require 'net/ssh'
3
2
 
4
3
  module VagrantPlugins
5
4
  module OneCloud
@@ -15,6 +14,8 @@ module VagrantPlugins
15
14
  end
16
15
 
17
16
  def call(env)
17
+ ssh_key_id = [env[:ssh_key_id]]
18
+
18
19
  # submit new droplet request
19
20
  result = @client.post('/server', {
20
21
  :HDD => @machine.provider_config.hdd,
@@ -24,6 +25,7 @@ module VagrantPlugins
24
25
  :DCLocation => @machine.provider_config.region,
25
26
  :ImageID => @machine.provider_config.image,
26
27
  :Name => @machine.config.vm.hostname || @machine.name,
28
+ :SshKeys => ssh_key_id,
27
29
  :isHighPerformance => @machine.provider_config.hi_perf
28
30
  }.delete_if { |k, v| v.nil? })
29
31
 
@@ -38,60 +40,29 @@ module VagrantPlugins
38
40
  # refresh droplet state with provider
39
41
  droplet = Provider.droplet(@machine, :refresh => true)
40
42
 
41
- # add public key to machine
42
- path = @machine.config.ssh.private_key_path
43
- path = path[0] if path.is_a?(Array)
44
- path = File.expand_path(path, @machine.env.root_path)
45
- pub_key = OneCloud.public_key(path)
46
- Net::SSH.start(droplet['IP'], droplet['AdminUserName'], :password => droplet['AdminPassword']) do |ssh|
47
- ssh.exec!("mkdir -p ~/.ssh")
48
- ssh.exec!("touch ~/.ssh/authorized_keys")
49
- ssh.exec!("echo \"#{pub_key}\" >> ~/.ssh/authorized_keys")
50
- ssh.exec!("chmod 600 ~/.ssh/authorized_keys")
51
- end
52
-
53
43
  user = @machine.config.ssh.username
54
44
  @machine.config.ssh.username = 'root'
55
45
 
56
46
  # wait for ssh to be ready
57
- $reboot_num = 3
58
- $check_num = 30
59
- $i = 0
60
- while $i <= $reboot_num do
61
- $j = 0
62
- while !@machine.communicate.ready? && $j < $check_num do
63
- env[:ui].info I18n.t('vagrant_1cloud.info.ssh_off')
64
- sleep 10
65
- $j += 1
66
- end
67
-
68
- if $j < $check_num
69
- env[:ui].info I18n.t('vagrant_1cloud.info.ssh_on')
70
- break
71
- else
72
- if $i < $reboot_num
73
- # submit reboot droplet request
74
- result = @client.post("/server/#{@machine.id}/action", {
75
- :Type => 'PowerReboot'
76
- })
77
-
78
- # wait for request to complete
79
- env[:ui].info I18n.t('vagrant_1cloud.info.reloading')
80
- @client.wait_for_event(env, @machine.id, result['body']['ID'])
81
-
82
- $i += 1
83
- else
84
- raise 'No ssh connection'
85
- end
86
- end
87
- end
47
+ env[:ui].info I18n.t('vagrant_1cloud.info.ssh')
48
+ @client.wait_for_ssh(env, 3, 30)
88
49
 
89
- # change host name
50
+ # change authorized_keys file permissions, host name and set public network rules
90
51
  @machine.communicate.execute(<<-BASH)
52
+ chmod 600 ~/.ssh/authorized_keys
53
+
91
54
  sed -i -e "s/127.0.1.1.*/127.0.1.1\t#{@machine.config.vm.hostname}/" /etc/hosts
92
55
  sed -i -e "s/#{droplet['IP']}.*/#{droplet['IP']}\t#{@machine.config.vm.hostname}/" /etc/hosts
93
56
  echo #{@machine.config.vm.hostname} > /etc/hostname
94
57
  hostname #{@machine.config.vm.hostname}
58
+
59
+ ifdown -a
60
+ export INTERFACE=eth0
61
+ export MATCHADDR=$(ifconfig -a | grep eth0 | awk '{print $NF}')
62
+ export MATCHID=$(udevadm info /sys/class/net/eth0 | grep P: | awk -F/ '{print $(NF-2)}')
63
+ /lib/udev/write_net_rules
64
+ udevadm control --reload-rules && udevadm trigger
65
+ ifup -a
95
66
  BASH
96
67
 
97
68
  @machine.config.ssh.username = user
@@ -30,37 +30,8 @@ module VagrantPlugins
30
30
  @machine.config.ssh.username = 'root'
31
31
 
32
32
  # wait for ssh to be ready
33
- $reboot_num = 3
34
- $check_num = 30
35
- $i = 0
36
- while $i <= $reboot_num do
37
- $j = 0
38
- while !@machine.communicate.ready? && $j < $check_num do
39
- env[:ui].info I18n.t('vagrant_1cloud.info.ssh_off')
40
- sleep 10
41
- $j += 1
42
- end
43
-
44
- if $j < $check_num
45
- env[:ui].info I18n.t('vagrant_1cloud.info.ssh_on')
46
- break
47
- else
48
- if $i < $reboot_num
49
- # submit reboot droplet request
50
- result = @client.post("/server/#{@machine.id}/action", {
51
- :Type => 'PowerReboot'
52
- })
53
-
54
- # wait for request to complete
55
- env[:ui].info I18n.t('vagrant_1cloud.info.reloading')
56
- @client.wait_for_event(env, @machine.id, result['body']['ID'])
57
-
58
- $i += 1
59
- else
60
- raise 'No ssh connection'
61
- end
62
- end
63
- end
33
+ env[:ui].info I18n.t('vagrant_1cloud.info.ssh')
34
+ @client.wait_for_ssh(env, 3, 30)
64
35
 
65
36
  @machine.config.ssh.username = user
66
37
 
@@ -20,36 +20,11 @@ module VagrantPlugins
20
20
  return @app.call(env) unless @machine.provider_config.private_net
21
21
 
22
22
  @machine.provider_config.private_net.each do |net, ip|
23
- lockfile = "/tmp/" + net.to_s + ".lock"
24
- f = File.open(lockfile, "w+")
25
-
26
- retryable(:tries => 400, :sleep => 10) do
27
- next if env[:interrupted]
28
- raise 'Problem with lockfile' if check_file_locked?(lockfile)
29
- end
30
-
31
- f.flock(File::LOCK_EX)
32
-
33
23
  # Getting private network by name
34
24
  result = @client.request('/network')
35
25
  private_network = result['body'].find { |network| network['Name'] == net.to_s }
36
26
 
37
- # Creating private network if it doesn't exist
38
- if !private_network
39
- result = @client.post("/network", {
40
- :Name => net,
41
- :IsDHCP => false,
42
- :DCLocation => @machine.provider_config.region
43
- })
44
- # Waiting for private network to create
45
- env[:ui].info I18n.t('vagrant_1cloud.info.creating_private_network')
46
- @client.wait_for_network(env, result['body']['ID'])
47
-
48
- result = @client.request("/network/#{result['body']['ID']}")
49
- private_network = result['body']
50
- end
51
-
52
- f.flock(File::LOCK_UN)
27
+ raise "Private network #{net} is not created" if !private_network
53
28
 
54
29
  # Adding server to specified network
55
30
  result = @client.post("/Server/#{@machine.id}/Action", {
@@ -75,20 +50,31 @@ module VagrantPlugins
75
50
  user = @machine.config.ssh.username
76
51
  @machine.config.ssh.username = 'root'
77
52
 
78
- # set private and public network
79
- @machine.communicate.execute(<<-BASH)
80
- ifdown -a
81
-
82
- export INTERFACE=eth0
83
- export MATCHADDR=$(ifconfig -a | grep eth0 | awk '{print $NF}')
84
- export MATCHID=$(udevadm info /sys/class/net/eth0 | grep P: | awk -F/ '{print $(NF-2)}')
53
+ # set private network rules
54
+ if private_network['IsDHCP']
55
+ @machine.communicate.execute(<<-BASH)
56
+ ifdown -a
57
+
58
+ export INTERFACE=$(ifconfig -a | grep #{linked_network['MAC']} | awk '{print $1}')
59
+ export MATCHADDR=#{linked_network['MAC']}
60
+ export MATCHID=$(ifconfig -a | grep #{linked_network['MAC']} | awk 'system("udevadm info /sys/class/net/" $1)' | grep P: | awk -F/ '{print $(NF-2)}')
85
61
  /lib/udev/write_net_rules
62
+ udevadm control --reload-rules && udevadm trigger
63
+
64
+ echo >> /etc/network/interfaces
65
+ ifconfig -a | grep #{linked_network['MAC']} | awk '{print "auto " $1}' >> /etc/network/interfaces
66
+ ifconfig -a | grep #{linked_network['MAC']} | awk '{print "iface " $1 " inet dhcp"}' >> /etc/network/interfaces
86
67
 
68
+ ifup -a
69
+ BASH
70
+ else
71
+ @machine.communicate.execute(<<-BASH)
72
+ ifdown -a
73
+
87
74
  export INTERFACE=$(ifconfig -a | grep #{linked_network['MAC']} | awk '{print $1}')
88
75
  export MATCHADDR=#{linked_network['MAC']}
89
76
  export MATCHID=$(ifconfig -a | grep #{linked_network['MAC']} | awk 'system("udevadm info /sys/class/net/" $1)' | grep P: | awk -F/ '{print $(NF-2)}')
90
77
  /lib/udev/write_net_rules
91
-
92
78
  udevadm control --reload-rules && udevadm trigger
93
79
 
94
80
  echo >> /etc/network/interfaces
@@ -98,7 +84,8 @@ module VagrantPlugins
98
84
  echo "netmask #{private_network['Mask']}" >> /etc/network/interfaces
99
85
 
100
86
  ifup -a
101
- BASH
87
+ BASH
88
+ end
102
89
 
103
90
  # reset username
104
91
  @machine.config.ssh.username = user
@@ -106,17 +93,6 @@ module VagrantPlugins
106
93
 
107
94
  @app.call(env)
108
95
  end
109
-
110
- def check_file_locked?(file)
111
- f = File.open(file, File::CREAT)
112
- Timeout::timeout(0.001) { f.flock(File::LOCK_EX) }
113
- f.flock(File::LOCK_UN)
114
- false
115
- rescue
116
- true
117
- ensure
118
- f.close
119
- end
120
96
  end
121
97
  end
122
98
  end
@@ -0,0 +1,78 @@
1
+ require 'vagrant-1cloud/helpers/client'
2
+ require 'net/ssh'
3
+
4
+ module VagrantPlugins
5
+ module OneCloud
6
+ module Actions
7
+ class Rebuild
8
+ include Helpers::Client
9
+ include Vagrant::Util::Retryable
10
+
11
+ def initialize(app, env)
12
+ @app = app
13
+ @machine = env[:machine]
14
+ @client = client
15
+ @logger = Log4r::Logger.new('vagrant::onecloud::rebuild')
16
+ end
17
+
18
+ def call(env)
19
+
20
+ # submit rebuild request
21
+ result = @client.post("/server/#{@machine.id}/rebuild", {
22
+ :ImageId => @machine.provider_config.image
23
+ })
24
+
25
+ # assign the machine id for reference in other commands
26
+ @machine.id = result['body']['ID'].to_s
27
+
28
+ # wait for request to complete
29
+ result = @client.request("/server/#{@machine.id}/action")
30
+ env[:ui].info I18n.t('vagrant_1cloud.info.rebuilding')
31
+ @client.wait_for_event(env, @machine.id, result['body'].first['ID'])
32
+
33
+ # refresh droplet state with provider
34
+ droplet = Provider.droplet(@machine, :refresh => true)
35
+
36
+ user = @machine.config.ssh.username
37
+ @machine.config.ssh.username = 'root'
38
+
39
+ # add public key to machine
40
+ ssh_key_name = @machine.provider_config.ssh_key_name
41
+ result = @client.request('/sshkey')
42
+ pub_key = result['body'].find { |k| k['Title'] == ssh_key_name }
43
+
44
+ Net::SSH.start(droplet['IP'], droplet['AdminUserName'], :password => droplet['AdminPassword']) do |ssh|
45
+ ssh.exec!("mkdir ~/.ssh")
46
+ ssh.exec!("touch ~/.ssh/authorized_keys")
47
+ ssh.exec!("echo \"ssh-rsa #{pub_key['PublicKey']}\" >> ~/.ssh/authorized_keys")
48
+ ssh.exec!("chmod 600 ~/.ssh/authorized_keys")
49
+ end
50
+
51
+ # wait for ssh to be ready
52
+ env[:ui].info I18n.t('vagrant_1cloud.info.ssh')
53
+ @client.wait_for_ssh(env, 3, 30)
54
+
55
+ # change authorized_keys file permissions, host name and set public network rules
56
+ @machine.communicate.execute(<<-BASH)
57
+ sed -i -e "s/127.0.1.1.*/127.0.1.1\t#{@machine.config.vm.hostname}/" /etc/hosts
58
+ sed -i -e "s/#{droplet['IP']}.*/#{droplet['IP']}\t#{@machine.config.vm.hostname}/" /etc/hosts
59
+ echo #{@machine.config.vm.hostname} > /etc/hostname
60
+ hostname #{@machine.config.vm.hostname}
61
+
62
+ ifdown -a
63
+ export INTERFACE=eth0
64
+ export MATCHADDR=$(ifconfig -a | grep eth0 | awk '{print $NF}')
65
+ export MATCHID=$(udevadm info /sys/class/net/eth0 | grep P: | awk -F/ '{print $(NF-2)}')
66
+ /lib/udev/write_net_rules
67
+ udevadm control --reload-rules && udevadm trigger
68
+ ifup -a
69
+ BASH
70
+
71
+ @machine.config.ssh.username = user
72
+
73
+ @app.call(env)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -27,37 +27,8 @@ module VagrantPlugins
27
27
  @machine.config.ssh.username = 'root'
28
28
 
29
29
  # wait for ssh to be ready
30
- $reboot_num = 3
31
- $check_num = 30
32
- $i = 0
33
- while $i <= $reboot_num do
34
- $j = 0
35
- while !@machine.communicate.ready? && $j < $check_num do
36
- env[:ui].info I18n.t('vagrant_1cloud.info.ssh_off')
37
- sleep 10
38
- $j += 1
39
- end
40
-
41
- if $j < $check_num
42
- env[:ui].info I18n.t('vagrant_1cloud.info.ssh_on')
43
- break
44
- else
45
- if $i < $reboot_num
46
- # submit reboot droplet request
47
- result = @client.post("/server/#{@machine.id}/action", {
48
- :Type => 'PowerReboot'
49
- })
50
-
51
- # wait for request to complete
52
- env[:ui].info I18n.t('vagrant_1cloud.info.reloading')
53
- @client.wait_for_event(env, @machine.id, result['body']['ID'])
54
-
55
- $i += 1
56
- else
57
- raise 'No ssh connection'
58
- end
59
- end
60
- end
30
+ env[:ui].info I18n.t('vagrant_1cloud.info.ssh')
31
+ @client.wait_for_ssh(env, 3, 30)
61
32
 
62
33
  @machine.config.ssh.username = user
63
34
 
@@ -0,0 +1,60 @@
1
+ require 'vagrant-1cloud/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module OneCloud
5
+ module Actions
6
+ class SetupKey
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @logger = Log4r::Logger.new('vagrant::onecloud::setup_key')
14
+ end
15
+
16
+ # TODO check the content of the key to see if it has changed
17
+ def call(env)
18
+ ssh_key_name = @machine.provider_config.ssh_key_name
19
+
20
+ begin
21
+ # assigns existing ssh key id to env for use by other commands
22
+ env[:ssh_key_id] = @client
23
+ .request('/sshkey')
24
+ .find_id(:body, :Title => ssh_key_name)
25
+
26
+ env[:ui].info I18n.t('vagrant_1cloud.info.using_key', {
27
+ :name => ssh_key_name
28
+ })
29
+ rescue Errors::ResultMatchError
30
+ env[:ssh_key_id] = create_ssh_key(ssh_key_name, env)
31
+ end
32
+
33
+ puts env[:ssh_key_id]
34
+
35
+ @app.call(env)
36
+ end
37
+
38
+ private
39
+
40
+ def create_ssh_key(name, env)
41
+ # assumes public key exists on the same path as private key with .pub ext
42
+ path = @machine.config.ssh.private_key_path
43
+ path = path[0] if path.is_a?(Array)
44
+ path = File.expand_path(path, @machine.env.root_path)
45
+ pub_key = OneCloud.public_key(path)
46
+
47
+ env[:ui].info I18n.t('vagrant_1cloud.info.creating_key', {
48
+ :name => name
49
+ })
50
+
51
+ result = @client.post('/sshkey', {
52
+ :Title => name,
53
+ :PublicKey => pub_key
54
+ })
55
+ result['body']['ID']
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,43 @@
1
+ module VagrantPlugins
2
+ module OneCloud
3
+ module Actions
4
+ class SetupSudo
5
+ def initialize(app, env)
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::onecloud::setup_sudo')
9
+ end
10
+
11
+ def call(env)
12
+ # override ssh username to root
13
+ user = @machine.config.ssh.username
14
+ @machine.config.ssh.username = 'root'
15
+
16
+ # check for guest name available in Vagrant 1.2 first
17
+ guest_name = @machine.guest.name if @machine.guest.respond_to?(:name)
18
+ guest_name ||= @machine.guest.to_s.downcase
19
+
20
+ case guest_name
21
+ when /debian/
22
+ env[:ui].info I18n.t('vagrant_1cloud.info.late_sudo_install_deb')
23
+ @machine.communicate.execute(<<-'BASH')
24
+ if [ ! -x /usr/bin/sudo ] ; then apt-get update -y && apt-get install -y sudo ; fi
25
+ BASH
26
+ when /redhat/
27
+ env[:ui].info I18n.t('vagrant_1cloud.info.modifying_sudo')
28
+
29
+ # disable tty requirement for sudo
30
+ @machine.communicate.execute(<<-'BASH')
31
+ sed -i'.bk' -e 's/\(Defaults\s\+requiretty\)/# \1/' /etc/sudoers
32
+ BASH
33
+ end
34
+
35
+ # reset ssh username
36
+ @machine.config.ssh.username = user
37
+
38
+ @app.call(env)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -23,7 +23,7 @@ module VagrantPlugins
23
23
  # create user account
24
24
  @machine.communicate.execute(<<-BASH)
25
25
  groupadd "#{user}"
26
- useradd -m -d "/home/#{user}" -g "#{user}" -r "#{user}"
26
+ useradd -m -d "/home/#{user}" -g "#{user}" -r "#{user}" -s "/bin/bash"
27
27
  chown #{user}:#{user} -R "/home/#{user}"
28
28
  BASH
29
29
 
@@ -0,0 +1,135 @@
1
+ require 'optparse'
2
+ require 'vagrant-1cloud/helpers/result'
3
+ require 'faraday'
4
+ require 'json'
5
+
6
+ module VagrantPlugins
7
+ module OneCloud
8
+ module Commands
9
+ class CreateNetwork < Vagrant.plugin('2', :command)
10
+ include Helpers
11
+ include Vagrant::Util::Retryable
12
+
13
+ # Show description when `vagrant list-commands` is triggered
14
+ def self.synopsis
15
+ "plugin: vagrant-1cloud: creates new private network"
16
+ end
17
+
18
+ def execute
19
+ options = {}
20
+
21
+ optparse = OptionParser.new do |opts|
22
+ opts.banner = 'Usage: vagrant create-network [options]'
23
+
24
+ opts.on('-n', '--name NAME', 'Network name') do |name|
25
+ options[:Name] = name
26
+ end
27
+
28
+ options[:IsDHCP] = false
29
+ opts.on('-d', '--[no-]dhcp', "Use dhcp or not (default #{options[:IsDHCP]})") do |dhcp|
30
+ options[:IsDHCP] = dhcp
31
+ end
32
+
33
+ opts.on('-l', '--location LOCATION', 'Network location') do |location|
34
+ options[:DCLocation] = location
35
+ end
36
+
37
+ opts.on('-t', '--token TOKEN', '1cloud type token') do |token|
38
+ options[:token] = token
39
+ end
40
+
41
+ opts.on('-h', '--help', 'Display this screen') do
42
+ puts opts
43
+ exit
44
+ end
45
+ end
46
+
47
+ begin
48
+ optparse.parse!
49
+ mandatory = [:Name, :DCLocation, :token]
50
+ missing = mandatory.select{ |param| options[param].nil? }
51
+ unless missing.empty?
52
+ raise OptionParser::MissingArgument.new(missing.join(', '))
53
+ end
54
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument
55
+ puts $!.to_s
56
+ puts optparse
57
+ exit
58
+ end
59
+
60
+ result = request(options[:token], '/network')
61
+ private_network = result['body'].find { |network| network['Name'] == options[:Name] }
62
+
63
+ if private_network
64
+ @env.ui.info I18n.t('vagrant_1cloud.info.network_exists', network: options[:Name])
65
+ else
66
+ @env.ui.info I18n.t('vagrant_1cloud.info.network_missing', network: options[:Name])
67
+
68
+ result = request(options[:token], '/network', options.except(:token), :post)
69
+
70
+ # Waiting for private network to create
71
+ @env.ui.info I18n.t('vagrant_1cloud.info.creating_private_network')
72
+ wait_for_network(options[:token], result['body']['ID'])
73
+ end
74
+
75
+ 0
76
+ end
77
+
78
+ def request(token, path, params = {}, method = :get)
79
+ connection = Faraday.new({
80
+ :url => 'https://api.1cloud.ru/'
81
+ })
82
+
83
+ begin
84
+ @env.ui.info I18n.t('vagrant_1cloud.info.request', path: path)
85
+ @env.ui.info I18n.t('vagrant_1cloud.info.params', params: params)
86
+ result = connection.send(method) do |req|
87
+ req.url path
88
+ req.headers['Authorization'] = "Bearer #{token}"
89
+ req.body = params
90
+ end
91
+ rescue Faraday::Error::ConnectionFailed => e
92
+ # TODO this is suspect but because faraday wraps the exception
93
+ # in something generic there doesn't appear to be another
94
+ # way to distinguish different connection errors :(
95
+ if e.message =~ /certificate verify failed/
96
+ raise Errors::CertificateError
97
+ end
98
+ raise e
99
+ end
100
+
101
+ begin
102
+ body = JSON.parse(%Q[{"body":#{result.body}}])
103
+ @env.ui.info I18n.t('vagrant_1cloud.info.response', body: body)
104
+ rescue JSON::ParserError => e
105
+ raise(Errors::JSONError, {
106
+ :message => e.message,
107
+ :path => path,
108
+ :params => params,
109
+ :response => result.body
110
+ })
111
+ end
112
+
113
+ unless /^2\d\d$/ =~ result.status.to_s
114
+ raise(Errors::APIStatusError, {
115
+ :path => path,
116
+ :params => params,
117
+ :status => result.status,
118
+ :response => body.inspect
119
+ })
120
+ end
121
+
122
+ Result.new(body)
123
+ end
124
+
125
+ def wait_for_network(token, net_id)
126
+ retryable(:tries => 400, :sleep => 10) do
127
+ # check network status
128
+ result = request(token, "/network/#{net_id}")
129
+ raise 'Network is not active' if result['body']['State'] != 'Active'
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,29 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module OneCloud
5
+ module Commands
6
+ class Rebuild < Vagrant.plugin('2', :command)
7
+
8
+ # Show description when `vagrant list-commands` is triggered
9
+ def self.synopsis
10
+ "plugin: vagrant-1cloud: destroys and ups the vm with the same ip address"
11
+ end
12
+
13
+ def execute
14
+ opts = OptionParser.new do |o|
15
+ o.banner = 'Usage: vagrant rebuild [vm-name]'
16
+ end
17
+
18
+ argv = parse_options(opts)
19
+
20
+ with_target_vms(argv) do |machine|
21
+ machine.action(:rebuild)
22
+ end
23
+
24
+ 0
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -11,6 +11,7 @@ module VagrantPlugins
11
11
  attr_accessor :hi_perf
12
12
  attr_accessor :ca_path
13
13
  attr_accessor :private_net
14
+ attr_accessor :ssh_key_name
14
15
 
15
16
  def initialize
16
17
  @token = UNSET_VALUE
@@ -23,6 +24,7 @@ module VagrantPlugins
23
24
  @hi_perf = UNSET_VALUE
24
25
  @ca_path = UNSET_VALUE
25
26
  @private_net = UNSET_VALUE
27
+ @ssh_key_name = UNSET_VALUE
26
28
  end
27
29
 
28
30
  def finalize!
@@ -36,6 +38,7 @@ module VagrantPlugins
36
38
  @hi_perf = false if @hi_perf == UNSET_VALUE
37
39
  @ca_path = nil if @ca_path == UNSET_VALUE
38
40
  @private_net = nil if @private_net == UNSET_VALUE
41
+ @ssh_key_name = 'Vagrant' if @ssh_key_name == UNSET_VALUE
39
42
  end
40
43
 
41
44
  def validate(machine)
@@ -56,4 +59,4 @@ module VagrantPlugins
56
59
  end
57
60
  end
58
61
  end
59
- end
62
+ end
@@ -17,6 +17,7 @@ module VagrantPlugins
17
17
  def initialize(machine)
18
18
  @logger = Log4r::Logger.new('vagrant::onecloud::apiclient')
19
19
  @config = machine.provider_config
20
+ @machine = machine
20
21
  @client = Faraday.new({
21
22
  :url => 'https://api.1cloud.ru/',
22
23
  :ssl => {
@@ -25,12 +26,12 @@ module VagrantPlugins
25
26
  })
26
27
  end
27
28
 
28
- def delete(path, params = {}, method = :delete)
29
+ def delete(path, params = {})
29
30
  @client.request :url_encoded
30
31
  request(path, params, :delete)
31
32
  end
32
33
 
33
- def post(path, params = {}, method = :post)
34
+ def post(path, params = {})
34
35
  @client.headers['Content-Type'] = 'application/json'
35
36
  request(path, params, :post)
36
37
  end
@@ -38,6 +39,7 @@ module VagrantPlugins
38
39
  def request(path, params = {}, method = :get)
39
40
  begin
40
41
  @logger.info "Request: #{path}"
42
+ @logger.info "Parameters: #{params}"
41
43
  result = @client.send(method) do |req|
42
44
  req.url path
43
45
  req.headers['Authorization'] = "Bearer #{@config.token}"
@@ -104,6 +106,38 @@ module VagrantPlugins
104
106
  raise 'Network is not active' if result['body']['State'] != 'Active'
105
107
  end
106
108
  end
109
+
110
+ def wait_for_ssh(env, reboot_num, check_num)
111
+ i = 0
112
+ while i <= reboot_num do
113
+ j = 0
114
+ while !@machine.communicate.ready? && j < check_num do
115
+ env[:ui].info I18n.t('vagrant_1cloud.info.ssh_off')
116
+ sleep 10
117
+ j += 1
118
+ end
119
+
120
+ if j < check_num
121
+ env[:ui].info I18n.t('vagrant_1cloud.info.ssh_on')
122
+ break
123
+ else
124
+ if i < reboot_num
125
+ # submit reboot droplet request
126
+ result = @client.post("/server/#{@machine.id}/action", {
127
+ :Type => 'PowerReboot'
128
+ })
129
+
130
+ # wait for request to complete
131
+ env[:ui].info I18n.t('vagrant_1cloud.info.reloading')
132
+ @client.wait_for_event(env, @machine.id, result['body']['ID'])
133
+
134
+ i += 1
135
+ else
136
+ raise 'No ssh connection'
137
+ end
138
+ end
139
+ end
140
+ end
107
141
  end
108
142
  end
109
143
  end
@@ -16,6 +16,16 @@ module VagrantPlugins
16
16
  require_relative 'provider'
17
17
  Provider
18
18
  end
19
+
20
+ command(:rebuild) do
21
+ require_relative 'commands/rebuild'
22
+ Commands::Rebuild
23
+ end
24
+
25
+ command("create-network") do
26
+ require_relative 'commands/create_network'
27
+ Commands::CreateNetwork
28
+ end
19
29
  end
20
30
  end
21
- end
31
+ end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module OneCloud
3
- VERSION = '1.0.7'
3
+ VERSION = '1.0.8'
4
4
  end
5
5
  end
@@ -1,21 +1,32 @@
1
1
  en:
2
2
  vagrant_1cloud:
3
3
  info:
4
- off: "Droplet is off"
5
- not_created: "Droplet has not been created"
6
- already_active: "Droplet is already active"
7
- already_off: "Droplet is already off"
8
- creating: "Creating a new droplet..."
9
- destroying: "Destroying the droplet..."
10
- shutting_down: "Shutting down the droplet..."
11
- powering_off: "Powering off the droplet..."
12
- powering_on: "Powering on the droplet..."
13
- reloading: "Rebooting the droplet..."
4
+ off: "VPS is off"
5
+ not_created: "VPS has not been created"
6
+ already_active: "VPS is already active"
7
+ already_off: "VPS is already off"
8
+ creating: "Creating a new VPS..."
9
+ destroying: "Destroying the VPS..."
10
+ shutting_down: "Shutting down the VPS..."
11
+ powering_off: "Powering off the VPS..."
12
+ powering_on: "Powering on the VPS..."
13
+ rebuilding: "Rebuilding the VPS..."
14
+ reloading: "Rebooting the VPS..."
14
15
  creating_user: "Creating user account: %{user}..."
16
+ late_sudo_install_deb: "1clouds's debian image lacks sudo. Installing now."
17
+ modifying_sudo: "Modifying sudoers file to remove tty requirement..."
18
+ using_key: "Using existing SSH key: %{name}"
19
+ creating_key: "Creating new SSH key: %{name}..."
15
20
  setting_private_network: "Setting private network..."
16
21
  creating_private_network: "Creating private network..."
22
+ ssh: "Waiting for ssh to be ready"
17
23
  ssh_off: "ssh connection is off"
18
24
  ssh_on: "ssh connection is on"
25
+ network_exists: "Private network %{network} already exists"
26
+ network_missing: "Private network %{network} is missing"
27
+ request: "Request: %{path}"
28
+ params: "Parameters: %{params}"
29
+ response: "Response: %{body}"
19
30
  config:
20
31
  token: "Token is required"
21
32
  private_key: "SSH private key path is required"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-1cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bulat Yusupov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-11 00:00:00.000000000 Z
11
+ date: 2017-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -62,6 +62,7 @@ files:
62
62
  - ".gitignore"
63
63
  - Gemfile
64
64
  - LICENSE
65
+ - README.md
65
66
  - Rakefile
66
67
  - lib/vagrant-1cloud.rb
67
68
  - lib/vagrant-1cloud/actions.rb
@@ -72,9 +73,14 @@ files:
72
73
  - lib/vagrant-1cloud/actions/power_off.rb
73
74
  - lib/vagrant-1cloud/actions/power_on.rb
74
75
  - lib/vagrant-1cloud/actions/private_network.rb
76
+ - lib/vagrant-1cloud/actions/rebuild.rb
75
77
  - lib/vagrant-1cloud/actions/reload.rb
78
+ - lib/vagrant-1cloud/actions/setup_key.rb
79
+ - lib/vagrant-1cloud/actions/setup_sudo.rb
76
80
  - lib/vagrant-1cloud/actions/setup_user.rb
77
81
  - lib/vagrant-1cloud/actions/shut_down.rb
82
+ - lib/vagrant-1cloud/commands/create_network.rb
83
+ - lib/vagrant-1cloud/commands/rebuild.rb
78
84
  - lib/vagrant-1cloud/config.rb
79
85
  - lib/vagrant-1cloud/errors.rb
80
86
  - lib/vagrant-1cloud/helpers/client.rb
@@ -108,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
114
  version: '0'
109
115
  requirements: []
110
116
  rubyforge_project:
111
- rubygems_version: 2.5.1
117
+ rubygems_version: 2.6.8
112
118
  signing_key:
113
119
  specification_version: 4
114
120
  summary: Enables Vagrant to manage 1cloud droplets. Based on https://github.com/devopsgroup-io/vagrant-digitalocean.