vagrant-1cloud 1.0.7 → 1.0.8

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