Skip to content

Commit

Permalink
Merge branch 'profiles2' of /gitlab/repositories/chef/chef-provisioni…
Browse files Browse the repository at this point in the history
…ng-opennebula into develop
  • Loading branch information
poliva83 committed Oct 29, 2015
2 parents 990cdcc + 6352016 commit 111ba48
Show file tree
Hide file tree
Showing 17 changed files with 215 additions and 39 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/.buildpath
/.project
/pkg/*
6 changes: 5 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ inherit_from: .rubocop_todo.yml
AllCops:
Exclude:
- 'vendor/**/*'
- 'spec/fixtures/**/*'
- 'spec/*'
- 'files/default/ha.rb'
- 'chef-provisioning-opennebula.gemspec'

AlignParameters:
Enabled: false
Expand Down Expand Up @@ -38,6 +39,9 @@ ParameterLists:
StringLiterals:
Enabled: false

Style/SignalException:
Enabled: false

Style/RescueModifier:
Description: 'Avoid using rescue in its modifier form.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-rescue-modifiers'
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 0.3.3 (10/24/2015)
- Changed driver_url to include profiles. Without profiles machine_file was unable to recreate the driver
and subsequently failed. The new driver_url format is:
opennebula:<endpoint_url>:<profile>
where profile is stored in ~/.one/one_config or ENV['ONE_CONFIG'] or /var/lig/one/.one/one_config file
- Added check for machine :destroy to verify that the VM is in DONE state. If not successful after 20 seconds
it will fail.
- opennebula 4.14 is not backwards compatible so there is a new gem dependency 'opennebula <4.14'.
- TODO: Support for 4.14

## 0.3.2 (10/8/2015)
- Fix rogue property bug

Expand Down
87 changes: 81 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,60 @@ Setup
-----
In order to use this driver with chef-provisioning the driver URL needs to be specified via environment variable or ```with_driver``` directive.

The driver URL has the following formats:
Starting in version 0.3.3 the driver URL has the following format:

```ruby
opennebula:<endpoint_url>
opennebula:<endpoint_url>:<profile>
```

The driver also requires credentials to connect to OpenNebula endpoint. These can be specified via ```driver_options```
Example:

```ruby
with_driver "opennebula:http://1.2.3.4:443/api:boggi"
```

Where ```boggi``` profile is stored the profile file. The file will be searched in the following order:
1. ```ENV['ONE_CONFIG']```
2. ```"#{ENV['HOME']}/.one/one_config"```
3. ```/var/lib/one/.one/one_config```

A sample one_config file would look like this:

```json
"boggi": {
"credentials": "boggi:my_token",
"options": {
"timeout": 2,
"sync": true,
"http_proxy": "http://my.proxy.com"
}
},
"testuser": {
"credentials": "testuser:test_token"
}
```

If no profile is specified the driver will attempt to read and use the ```ENV['ONE_AUTH']``` file or ```~/.one/one_auth``` or ```/var/lib/one/.one/one_auth```.
The driver is still backward compatible with previous format and passing ```:secret_file``` or ```:credentials``` in```:driver_options```.

Additional options to OpenNebual client can be passed vi ```:one_options```.

```ruby
with_driver "opennebula:http://1.2.3.4/endpoint:port",
:credentials => "<username>:<text_password>"
:credentials => "<username>:<text_password>",
:one_options => { :timeout => 3 }
```

or

```ruby
with_driver "opennebula:http://1.2.3.4/endpoint:port",
:secret_file => "<local_path_to_file_with_credentials>"
:secret_file => "<local_path_to_file_with_credentials>",
:one_options => { :timeout => 3 }
```

If additional OpenNebula client options need to be passed they can be specified as a hash ```:one_options => {}```.

In context of OpenNebula ```machine``` resource will take the following additional options:

```ruby
Expand All @@ -41,7 +75,7 @@ machine_options {
:template_file => String location of the VM template file,
:template_name => String name of the OpenNebula template to use
:template_id => Integer id of the OpenNebula template to use
:template_options => Hash values to be overwriten/added in VM template
:template_options => Hash values to be merged with VM template
:enforce_chef_fqdn => [TrueClass, FalseClass] flag indicating if fqdn names should be used for machine names
:is_shutdown => [TrueClass, FalseClass] call vm.shutodwn instead of vm.stop during :stop action
:shutdown_hard => [TrueClass, FalseClass] flag indicating hard or soft shutdown
Expand Down Expand Up @@ -455,3 +489,44 @@ ENV['ONE_AUTH'] - the path to your one_auth file
ENV['ONE_HTTPBASE'] - the base URL from which files are downloaded eg. chef-client.deb, init.sh, service.gz etc.
ENV['CHEF_REPO_PATH'] - the path to your local chef repo
```

## <a name="development"></a> Development

* Source hosted at [GitHub][repo]
* Report issues/questions/feature requests on [GitHub Issues][issues]

Pull requests are very welcome! Make sure your patches are well tested.
Ideally create a topic branch for every separate change you make. For
example:

1. Fork the repo
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

## <a name="authors"></a> Authors

Created by [Bogdan Buczynski][author] (<bbuczynski@blackberry.com>)

## <a name="maintainers"></a> Maintainers

Maintained by
* [Bogdan Buczynski][author] (<bbuczynski@blackberry.com>)
* [Philip Oliva][maintainer] (<philoliva8@gmail.com>)
* [Andrew J. Brown][maintainer] (<anbrown@blackberry.com>)
* [Evgeny Yurchenko][maintainer] (<eyurchenko@blackberry.com>)

## <a name="license"></a> License

Apache 2.0 (see [LICENSE][license])

[author]: https://github.com/bbuczynski
[maintainer]: https://github.com/poliva83
[maintainer]: https://github.com/andrewjamesbrown
[maintainer]: https://github.com/EYurchenko
[issues]: https://github.com/blackberry/chef-provisioning-opennebula/issues
[license]: https://github.com/blackberry/chef-provisioning-opennebula/blob/master/LICENSE
[repo]: https://github.com/blackberry/chef-provisioning-opennebula
[driver_usage]: https://github.com/chef/chef-provisioning/blob/master/docs/building_drivers.md#writing-drivers
[chefdk_dl]: https://downloads.chef.io/chef-dk/
2 changes: 1 addition & 1 deletion chef-provisioning-opennebula.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Gem::Specification.new do |s|

s.add_dependency 'chef'
s.add_dependency 'chef-provisioning', '> 0.15'
s.add_dependency 'opennebula', '~> 4.10'
s.add_dependency 'opennebula', '~> 4.10', '< 4.14'

s.add_development_dependency 'rspec'
s.add_development_dependency 'rake'
Expand Down
2 changes: 1 addition & 1 deletion lib/chef/provider/one_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def exists?
template_str = File.read(new_resource.template_file) if new_resource.template_file
template_str = new_driver.one.create_template(new_resource.template) if new_resource.template
template_str << "\nNAME=\"#{new_resource.name}\""
@template = new_driver.one.allocate_template(new_resource.name, template_str)
@template = new_driver.one.allocate_template(template_str)
@new_resource.updated_by_last_action(true)
end
end
Expand Down
3 changes: 1 addition & 2 deletions lib/chef/provider/one_vnet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def exists?(filter)
else
action_handler.perform_action "created vnet '#{@new_resource.name}' from '#{@new_resource.template_file}'" do
template_str = ::File.read(@new_resource.template_file) + "\nNAME=\"#{@new_resource.name}\""
vnet = OpenNebula::Vnet.new(OpenNebula::Vnet.build_xml, @client)
vnet = vnet.allocate(template_str, @new_resource.cluster_id) unless OpenNebula.is_error?(vnet)
vnet = new_driver.one.allocate_vnet(template_str, @new_resource.cluster_id)
Chef::Log.debug(template_str)
fail "failed to create vnet '#{@new_resource.name}': #{vnet.message}" if OpenNebula.is_error?(vnet)
@new_resource.updated_by_last_action(true)
Expand Down
1 change: 1 addition & 0 deletions lib/chef/provisioning/opennebula_driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
require 'chef/provisioning'
require 'chef/provisioning/opennebula_driver/driver'
require 'chef/provisioning/opennebula_driver/resources'
require 'chef/provisioning/opennebula_driver/credentials'
61 changes: 57 additions & 4 deletions lib/chef/provisioning/opennebula_driver/credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

require 'json'

#
# Implementation of Provider class.
#
Expand All @@ -28,9 +30,10 @@ module OpenNebulaDriver
# Implementation of Provider class.
#
class Credentials
def initialize
def initialize(options = {})
@credentials = {}
load_default
load_default(options)
load_profiles
end

def default
Expand All @@ -39,12 +42,62 @@ def default
end

def [](name)
fail "Profile '#{name}' does not exist" unless @credentials[name]
@credentials[name]
end

def load_default
def load_default(options = {})
oneauth_file = ENV['ONE_AUTH'] || File.expand_path('~/.one/one_auth')
@credentials['default'] = File.read(oneauth_file).strip! if File.file?(oneauth_file)
begin
creds = File.read(oneauth_file).strip
@credentials['default'] = { :credentials => creds, :options => options }
end if File.file?(oneauth_file)
end

def load_profiles
file = nil
if ENV['ONE_CONFIG'] && !ENV['ONE_CONFIG'].empty? && File.file?(ENV['ONE_CONFIG'])
file = ENV['ONE_CONFIG']
elsif ENV['HOME'] && File.file?("#{ENV['HOME']}/.one/one_config")
file = "#{ENV['HOME']}/.one/one_config"
elsif File.file?("/var/lib/one/.one/one_config")
file = "/var/lib/one/.one/one_config"
else
Chef::Log.info("No ONE_CONFIG file found, will use default profile")
end
json = {}
begin
content_hash = JSON.parse(File.read(file), :symbolize_names => true)
content_hash.each { |k, v| json[k.to_s] = v }
rescue Exception => e
Chef::Log.warn("Failed to read and parse config file #{file}: #{e.message}")
end
@credentials.merge!(json)
end

def load_plain(creds, options = {})
@credentials['default'] = {
:credentials => creds,
:options => options
} unless creds.nil?
@credentials
end

def load_file(filename, options = {})
creds = File.read(filename).strip if File.file?(filename)
@credentials['default'] = {
:credentials => creds,
:options => options
} unless creds.nil?
@credentials
end

def self.method_missing(name, *args, &block)
singleton.send(name, *args, &block)
end

def self.singleton
@one_credentials ||= Credentials.new
end
end
end
Expand Down
35 changes: 31 additions & 4 deletions lib/chef/provisioning/opennebula_driver/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
require 'chef/provisioning/transport/ssh'
require 'chef/provisioning/opennebula_driver/version'
require 'chef/provisioning/opennebula_driver/one_lib'
require 'chef/provisioning/opennebula_driver/credentials'

class Chef
module Provisioning
Expand Down Expand Up @@ -74,16 +75,23 @@ class Driver < Chef::Provisioning::Driver
# endpoint from ENV['ONE_XMLRPC']
#
# driver_url format:
# opennebula:<endpoint>
# opennebula:<endpoint>:<profile>
# where <profile> points to a one_auth file in ENV['HOME']/.one/<profile>
#
# driver_options:
# credentials: bbsl-auto:text_pass credentials has precedence over secret_file
# secret_file: local_path_to_one_auth_file
#
def initialize(driver_url, config)
super
credentials = driver_options[:credentials] || File.read(driver_options[:secret_file]).strip rescue nil
@one = OneLib.new(credentials, driver_url.split(':', 2)[1], driver_options[:one_options] || {})
scan = driver_url.match(%r/(opennebula):(https?:\/\/[^:\/]+ (?::[0-9]{2,5})? (?:\/[^:\s]+) ) :?([^:\s]+)?/x)
endpoint = scan[2]
profile_name = scan[3]
fail "OpenNebula endpoint must be specified in 'driver_url': #{driver_url}" if endpoint.nil?

profile = profile_name ? one_credentials[profile_name] : one_credentials.default
Chef::Log.warn("':credentials' and ':secret_file' will be deprecated in next version in favour of 'opennebula:<endpoint>:<profile_name>'") if profile_name.nil?
@one = OneLib.new(profile[:credentials], endpoint, profile[:options] || {})
end

def self.from_url(driver_url, config)
Expand All @@ -93,7 +101,7 @@ def self.from_url(driver_url, config)
# URL _must_ have an endpoint to prevent machine moving, which
# is not possible today between different endpoints.
def self.canonicalize_url(driver_url, config)
["opennebula:#{driver_url.split(':', 2)[1]}", config]
[driver_url, config]
end

# Allocate a machine from the underlying service. This method
Expand Down Expand Up @@ -206,6 +214,13 @@ def destroy_machine(action_handler, machine_spec, machine_options)
if !instance.nil?
action_handler.perform_action "destroyed machine #{machine_spec.name} (#{machine_spec.reference['instance_id']})" do
instance.delete
1.upto(10) do
instance.info
break if instance.state_str == 'DONE'
Chef::Log.debug("Waiting for VM '#{instance.id}' to be in 'DONE' state: '#{instance.state_str}'")
sleep(2)
end
fail "Failed to destroy '#{instance.name}'. Current state: #{instance.state_str}" if instance.state_str != 'DONE'
end
else
Chef::Log.info("vm #{machine_spec.name} (#{machine_spec.reference['instance_id']}) does not exist - nothing to do")
Expand Down Expand Up @@ -414,6 +429,18 @@ def destroy_load_balancer(_action_handler, _lb_spec, _lb_options)

protected

def one_credentials
@one_credentials ||= begin
credentials = Credentials.new(driver_options[:one_options] || {})
if driver_options[:credentials]
credentials.load_plain(driver_options[:credentials], driver_options[:one_options] || {})
elsif driver_options[:secret_file]
credentials.load_file(driver_options[:secret_file], driver_options[:one_options] || {})
end
credentials
end
end

def check_unique_names(bootstrap_options, machine_spec)
fail "VM with name '#{machine_spec.name}' already exists" unless @one.get_resource('vm', :name => machine_spec.name).nil? if bootstrap_options[:unique_names]
end
Expand Down
Loading

0 comments on commit 111ba48

Please sign in to comment.