New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First implementation of Heat Stacks #170
Changes from all commits
91d3782
e3d619d
2a0782f
ed5e451
b63f37b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
require 'log4r' | ||
require 'socket' | ||
require 'timeout' | ||
require 'sshkey' | ||
require 'yaml' | ||
|
||
require 'vagrant-openstack-provider/config_resolver' | ||
require 'vagrant-openstack-provider/utils' | ||
require 'vagrant-openstack-provider/action/abstract_action' | ||
require 'vagrant/util/retryable' | ||
|
||
module VagrantPlugins | ||
module Openstack | ||
module Action | ||
class CreateStack < AbstractAction | ||
def initialize(app, _env) | ||
@app = app | ||
@logger = Log4r::Logger.new('vagrant_openstack::action::create_stack') | ||
end | ||
|
||
def execute(env) | ||
@logger.info 'Start create stacks action' | ||
|
||
config = env[:machine].provider_config | ||
|
||
heat = env[:openstack_client].heat | ||
|
||
config.stacks.each do |stack| | ||
env[:ui].info(I18n.t('vagrant_openstack.create_stack')) | ||
env[:ui].info(" -- Stack Name : #{stack[:name]}") | ||
env[:ui].info(" -- Template : #{stack[:template]}") | ||
|
||
create_opts = { | ||
name: stack[:name], | ||
template: YAML.load_file(stack[:template]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, heat template can be either yaml or json. But no problem to handle json compatibility in a further pull request. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, will add this in heat issues |
||
} | ||
|
||
stack_id = heat.create_stack(env, create_opts) | ||
|
||
file_path = "#{env[:machine].data_dir}/stack_#{stack[:name]}_id" | ||
File.write(file_path, stack_id) | ||
|
||
waiting_for_stack_to_be_created(env, stack[:name], stack_id) | ||
end unless config.stacks.nil? | ||
|
||
@app.call(env) | ||
end | ||
|
||
private | ||
|
||
def waiting_for_stack_to_be_created(env, stack_name, stack_id, retry_interval = 3, timeout = 200) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I plan to refactor all the "waiting for ... to be ..." methods in a future patch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to #141 |
||
@logger.info "Waiting for the stack with id #{stack_id} to be built..." | ||
env[:ui].info(I18n.t('vagrant_openstack.waiting_for_stack')) | ||
timeout(timeout, Errors::Timeout) do | ||
stack_status = 'CREATE_IN_PROGRESS' | ||
until stack_status == 'CREATE_COMPLETE' | ||
@logger.debug('Waiting for stack to be CREATED') | ||
stack_status = env[:openstack_client].heat.get_stack_details(env, stack_name, stack_id)['stack_status'] | ||
fail Errors::StackStatusError, stack: stack_id if stack_status == 'CREATE_FAILED' | ||
sleep retry_interval | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
require 'log4r' | ||
require 'socket' | ||
require 'timeout' | ||
require 'sshkey' | ||
require 'yaml' | ||
|
||
require 'vagrant-openstack-provider/config_resolver' | ||
require 'vagrant-openstack-provider/utils' | ||
require 'vagrant-openstack-provider/action/abstract_action' | ||
require 'vagrant/util/retryable' | ||
|
||
module VagrantPlugins | ||
module Openstack | ||
module Action | ||
class DeleteStack < AbstractAction | ||
def initialize(app, _env) | ||
@app = app | ||
@logger = Log4r::Logger.new('vagrant_openstack::action::delete_stack') | ||
end | ||
|
||
def execute(env) | ||
@logger.info 'Start delete stacks action' | ||
|
||
heat = env[:openstack_client].heat | ||
|
||
list_stack_files(env).each do |stack| | ||
env[:ui].info(I18n.t('vagrant_openstack.delete_stack')) | ||
env[:ui].info(" -- Stack Name : #{stack[:name]}") | ||
env[:ui].info(" -- Stack Id : #{stack[:id]}") | ||
|
||
heat.delete_stack(env, stack[:name], stack[:id]) | ||
|
||
waiting_for_stack_to_be_deleted(env, stack[:name], stack[:id]) | ||
end | ||
|
||
# This will remove all files in the .vagrant instance directory | ||
env[:machine].id = nil | ||
|
||
@app.call(env) | ||
end | ||
|
||
private | ||
|
||
def list_stack_files(env) | ||
stack_files = [] | ||
Dir.glob("#{env[:machine].data_dir}/stack_*_id") do |stack_file| | ||
file_name = stack_file.split('/')[-1] | ||
stack_files << { | ||
name: file_name[6, (file_name.length) - 9], | ||
id: File.read("#{stack_file}") | ||
} | ||
end | ||
stack_files | ||
end | ||
|
||
def waiting_for_stack_to_be_deleted(env, stack_name, stack_id, retry_interval = 3, timeout = 200) | ||
@logger.info "Waiting for the stack with id #{stack_id} to be deleted..." | ||
env[:ui].info(I18n.t('vagrant_openstack.waiting_for_stack_deleted')) | ||
timeout(timeout, Errors::Timeout) do | ||
stack_status = 'DELETE_IN_PROGRESS' | ||
until stack_status == 'DELETE_COMPLETE' | ||
@logger.debug('Waiting for stack to be DELETED') | ||
stack_status = env[:openstack_client].heat.get_stack_details(env, stack_name, stack_id)['stack_status'] | ||
fail Errors::StackStatusError, stack: stack_id if stack_status == 'DELETE_FAILED' | ||
sleep retry_interval | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
require 'log4r' | ||
require 'restclient' | ||
require 'json' | ||
|
||
require 'vagrant-openstack-provider/client/http_utils' | ||
require 'vagrant-openstack-provider/client/domain' | ||
|
||
module VagrantPlugins | ||
module Openstack | ||
class HeatClient | ||
include Singleton | ||
include VagrantPlugins::Openstack::HttpUtils | ||
include VagrantPlugins::Openstack::Domain | ||
|
||
def initialize | ||
@logger = Log4r::Logger.new('vagrant_openstack::glance') | ||
@session = VagrantPlugins::Openstack.session | ||
end | ||
|
||
def create_stack(env, options) | ||
stack = {}.tap do |s| | ||
s['stack_name'] = options[:name] if options[:name] | ||
s['template'] = options[:template] | ||
end | ||
stack_res = post(env, "#{@session.endpoints[:orchestration]}/stacks", stack.to_json) | ||
JSON.parse(stack_res)['stack']['id'] | ||
end | ||
|
||
def get_stack_details(env, stack_name, stack_id) | ||
stack_exists do | ||
server_details = get(env, "#{@session.endpoints[:orchestration]}/stacks/#{stack_name}/#{stack_id}") | ||
JSON.parse(server_details)['stack'] | ||
end | ||
end | ||
|
||
def delete_stack(env, stack_name, stack_id) | ||
stack_exists do | ||
delete(env, "#{@session.endpoints[:orchestration]}/stacks/#{stack_name}/#{stack_id}") | ||
end | ||
end | ||
|
||
def stack_exists | ||
return yield | ||
rescue Errors::VagrantOpenstackError => e | ||
raise Errors::StackNotFound if e.extra_data[:code] == 404 | ||
raise e | ||
end | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When there's no stack declared in the Vagrantfile. Should be fixed by
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done