Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add OpenStack Deployer

Change-Id: I1591f6063ba02c04249422c191b77a2d019d9491
  • Loading branch information...
commit 6dcee09c2453a3f515503898c5ecba9c8807c11a 1 parent 72c1099
Ferran Rodenas frodenas authored
Showing with 793 additions and 1 deletion.
  1. +20 −0 deployer/Gemfile.lock
  2. +1 −0  deployer/bosh_deployer.gemspec
  3. +50 −0 deployer/config/openstack_defaults.yml
  4. +1 −1  deployer/lib/deployer/instance_manager.rb
  5. +256 −0 deployer/lib/deployer/instance_manager/openstack.rb
  6. +131 −0 deployer/spec/assets/apply_spec_openstack.yml
  7. 0  deployer/spec/assets/openstack_registry
  8. +24 −0 deployer/spec/assets/test-bootstrap-config-openstack.yml
  9. +93 −0 deployer/spec/unit/openstack/config_spec.rb
  10. +217 −0 deployer/spec/unit/openstack/instance_manager_spec.rb
  11. BIN  deployer/vendor/cache/bosh_openstack_cpi-0.0.2.gem
  12. BIN  deployer/vendor/cache/excon-0.14.3.gem
  13. BIN  deployer/vendor/cache/fog-1.4.0.gem
  14. BIN  deployer/vendor/cache/formatador-0.2.3.gem
  15. BIN  deployer/vendor/cache/httparty-0.8.1.gem
  16. BIN  deployer/vendor/cache/httparty-0.8.3.gem
  17. BIN  deployer/vendor/cache/json-1.6.6.gem
  18. BIN  deployer/vendor/cache/json-1.7.3.gem
  19. BIN  deployer/vendor/cache/multi_xml-0.4.2.gem
  20. BIN  deployer/vendor/cache/multi_xml-0.5.1.gem
  21. BIN  deployer/vendor/cache/nokogiri-1.5.2.gem
  22. BIN  deployer/vendor/cache/nokogiri-1.5.5.gem
  23. BIN  deployer/vendor/cache/sequel-3.33.0.gem
  24. BIN  deployer/vendor/cache/sequel-3.37.0.gem
  25. BIN  deployer/vendor/cache/sqlite3-1.3.5.gem
  26. BIN  deployer/vendor/cache/sqlite3-1.3.6.gem
20 deployer/Gemfile.lock
View
@@ -6,6 +6,7 @@ PATH
bosh_aws_cpi (~> 0.6.0)
bosh_common (~> 0.4.0)
bosh_cpi (~> 0.4.2)
+ bosh_openstack_cpi (~> 0.0.2)
bosh_vsphere_cpi (~> 0.4.9)
sqlite3 (~> 1.3.3)
@@ -52,6 +53,13 @@ GEM
bosh_common (0.4.0)
bosh_cpi (0.4.3)
bosh_common
+ bosh_openstack_cpi (0.0.2)
+ bosh_common (>= 0.4.0)
+ bosh_cpi (>= 0.4.3)
+ fog (>= 1.4.0)
+ httpclient (>= 2.2.0)
+ uuidtools (>= 2.1.2)
+ yajl-ruby (>= 0.8.2)
bosh_vsphere_cpi (0.4.9)
bosh_common
bosh_cpi (>= 0.4.2)
@@ -63,6 +71,18 @@ GEM
builder (>= 2.1.2)
columnize (0.3.6)
diff-lcs (1.1.3)
+ excon (0.14.3)
+ fog (1.4.0)
+ builder
+ excon (~> 0.14.0)
+ formatador (~> 0.2.0)
+ mime-types
+ multi_json (~> 1.0)
+ net-scp (~> 1.0.4)
+ net-ssh (>= 2.1.3)
+ nokogiri (~> 1.5.0)
+ ruby-hmac
+ formatador (0.2.3)
highline (1.6.11)
httparty (0.8.3)
multi_json (~> 1.0)
1  deployer/bosh_deployer.gemspec
View
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
s.add_dependency "bosh_cpi", "~>0.4.2"
s.add_dependency "bosh_vsphere_cpi", "~>0.4.9"
s.add_dependency "bosh_aws_cpi", "~>0.6.0"
+ s.add_dependency "bosh_openstack_cpi", "~>0.0.2"
s.add_dependency "agent_client", "~>0.1.1"
s.add_dependency "sqlite3", "~>1.3.3"
end
50 deployer/config/openstack_defaults.yml
View
@@ -0,0 +1,50 @@
+---
+name:
+
+logging:
+ level: INFO
+
+dir:
+
+network:
+ type: dynamic
+ cloud_properties: {}
+
+env:
+ bosh:
+ password:
+
+resources:
+ persistent_disk: 4096
+ cloud_properties:
+ instance_type: m1.small
+ availability_zone:
+
+cloud:
+ plugin: openstack
+ properties:
+ openstack:
+ auth_url:
+ username:
+ api_key:
+ tenant:
+ default_key_name:
+ default_security_groups: []
+ ssh_user: vcap
+ registry:
+ endpoint: http://admin:admin@localhost:25889
+ user: admin
+ password: admin
+ stemcell:
+ kernel_id:
+ disk: 4096
+ agent:
+ ntp: []
+ blobstore:
+ plugin: local
+ properties:
+ blobstore_path: /var/vcap/micro_bosh/data/cache
+ mbus:
+
+apply_spec:
+ properties: {}
2  deployer/lib/deployer/instance_manager.rb
View
@@ -350,7 +350,7 @@ def update_spec(spec)
properties["director"]["name"] = Config.name
end
- %w{blobstore postgres director redis nats aws_registry}.each do |service|
+ %w{blobstore postgres director redis nats aws_registry openstack_registry}.each do |service|
next unless properties[service]
properties[service]["address"] = service_ip
256 deployer/lib/deployer/instance_manager/openstack.rb
View
@@ -0,0 +1,256 @@
+# Copyright (c) 2009-2012 VMware, Inc.
+
+require 'net/ssh'
+
+module Bosh::Deployer
+ class InstanceManager
+
+ class Openstack < InstanceManager
+
+ def update_spec(spec)
+ spec = super(spec)
+ properties = spec["properties"]
+
+ properties["openstack"] =
+ Config.spec_properties["openstack"] ||
+ Config.cloud_options["properties"]["openstack"].dup
+
+ properties["openstack"]["registry"] = Config.cloud_options["properties"]["registry"]
+ properties["openstack"]["stemcell"] = Config.cloud_options["properties"]["stemcell"]
+
+ spec.delete("networks")
+
+ spec
+ end
+
+ def configure
+ properties = Config.cloud_options["properties"]
+ @ssh_user = properties["openstack"]["ssh_user"]
+ @ssh_port = properties["openstack"]["ssh_port"] || 22
+ @ssh_wait = properties["openstack"]["ssh_wait"] || 60
+
+ key = properties["openstack"]["private_key"]
+ unless key
+ raise ConfigError, "Missing properties.openstack.private_key"
+ end
+ @ssh_key = File.expand_path(key)
+ unless File.exists?(@ssh_key)
+ raise ConfigError, "properties.openstack.private_key '#{key}' does not exist"
+ end
+
+ uri = URI.parse(properties["registry"]["endpoint"])
+ user, password = uri.userinfo.split(":", 2)
+ @registry_port = uri.port
+
+ @registry_db = Tempfile.new("openstack_registry_db")
+ @registry_db_url = "sqlite://#{@registry_db.path}"
+
+ registry_config = {
+ "logfile" => "./openstack_registry.log",
+ "http" => {
+ "port" => uri.port,
+ "user" => user,
+ "password" => password
+ },
+ "db" => {
+ "database" => @registry_db_url
+ },
+ "openstack" => properties["openstack"]
+ }
+
+ @registry_config = Tempfile.new("openstack_registry_yml")
+ @registry_config.write(YAML.dump(registry_config))
+ @registry_config.close
+ end
+
+ def start
+ configure()
+
+ Sequel.connect(@registry_db_url) do |db|
+ migrate(db)
+ servers = @deployments["openstack_servers"]
+ db[:openstack_servers].insert_multiple(servers) if servers
+ end
+
+ unless has_openstack_registry?
+ raise "openstack_registry command not found - " +
+ "run 'gem install bosh_openstack_registry'"
+ end
+
+ cmd = "openstack_registry -c #{@registry_config.path}"
+
+ @registry_pid = spawn(cmd)
+
+ 5.times do
+ sleep 0.5
+ if Process.waitpid(@registry_pid, Process::WNOHANG)
+ raise Error, "`#{cmd}` failed, exit status=#{$?.exitstatus}"
+ end
+ end
+
+ timeout_time = Time.now.to_f + (60 * 5)
+ http_client = HTTPClient.new()
+ begin
+ http_client.head("http://127.0.0.1:#{@registry_port}")
+ sleep 0.5
+ rescue URI::Error, SocketError, Errno::ECONNREFUSED => e
+ if timeout_time - Time.now.to_f > 0
+ retry
+ else
+ raise "Cannot access openstack_registry: #{e.message}"
+ end
+ end
+ logger.info("openstack_registry is ready on port #{@registry_port}")
+ ensure
+ @registry_config.unlink if @registry_config
+ end
+
+ def stop
+ if @registry_pid && process_exists?(@registry_pid)
+ Process.kill("INT", @registry_pid)
+ Process.waitpid(@registry_pid)
+ end
+
+ return unless @registry_db_url
+
+ Sequel.connect(@registry_db_url) do |db|
+ @deployments["openstack_servers"] = db[:openstack_servers].map {|row| row}
+ end
+
+ save_state
+ @registry_db.unlink if @registry_db
+ end
+
+ def wait_until_agent_ready
+ tunnel(@registry_port)
+ super
+ end
+
+ def discover_bosh_ip
+ if exists?
+ server = cloud.openstack.servers.get(state.vm_cid)
+ ip = server.public_ip_address
+ ip = server.private_ip_address if ip.nil? || ip.empty?
+ if ip.nil? || ip.empty?
+ raise "Unable to discover bosh ip"
+ else
+ if ip["addr"] != Config.bosh_ip
+ Config.bosh_ip = ip["addr"]
+ logger.info("discovered bosh ip=#{Config.bosh_ip}")
+ end
+ end
+ end
+
+ super
+ end
+
+ def service_ip
+ ip = cloud.openstack.servers.get(state.vm_cid).private_ip_address
+ ip["addr"] unless ip.nil? || ip.empty?
+ end
+
+ # @return [Integer] size in MiB
+ def disk_size(cid)
+ # OpenStack stores disk size in GiB but we work with MiB
+ cloud.openstack.volumes.get(cid).size * 1024
+ end
+
+ def persistent_disk_changed?
+ # since OpenStack stores disk size in GiB and we use MiB there
+ # is a risk of conversion errors which lead to an unnecessary
+ # disk migration, so we need to do a double conversion
+ # here to avoid that
+ requested = (Config.resources['persistent_disk'] / 1024.0).ceil * 1024
+ requested != disk_size(state.disk_cid)
+ end
+
+ private
+
+ # TODO this code is similar to has_stemcell_copy?
+ # move the two into bosh_common later
+ def has_openstack_registry?(path=ENV['PATH'])
+ path.split(":").each do |dir|
+ return true if File.exist?(File.join(dir, "openstack_registry"))
+ end
+ false
+ end
+
+ def migrate(db)
+ db.create_table :openstack_servers do
+ primary_key :id
+ column :server_id, :text, :unique => true, :null => false
+ column :settings, :text, :null => false
+ end
+ end
+
+ def process_exists?(pid)
+ begin
+ Process.kill(0, pid)
+ rescue Errno::ESRCH
+ false
+ end
+ end
+
+ def socket_readable?(ip, port)
+ socket = TCPSocket.new(ip, port)
+ if IO.select([socket], nil, nil, 5)
+ logger.debug("tcp socket #{ip}:#{port} is readable")
+ yield
+ true
+ else
+ false
+ end
+ rescue SocketError => e
+ logger.debug("tcp socket #{ip}:#{port} SocketError: #{e.inspect}")
+ sleep 1
+ false
+ rescue SystemCallError => e
+ logger.debug("tcp socket #{ip}:#{port} SystemCallError: #{e.inspect}")
+ sleep 1
+ false
+ ensure
+ socket.close if socket
+ end
+
+ def tunnel(port)
+ return if @session
+
+ ip = discover_bosh_ip
+
+ loop until socket_readable?(ip, @ssh_port) do
+ #sshd is up, sleep while host keys are generated
+ sleep @ssh_wait
+ end
+
+ lo = "127.0.0.1"
+ cmd = "ssh -R #{port}:#{lo}:#{port} #{@ssh_user}@#{ip}"
+
+ logger.info("Preparing for ssh tunnel: #{cmd}")
+ loop do
+ begin
+ @session = Net::SSH.start(ip, @ssh_user, :keys => [@ssh_key],
+ :paranoid => false)
+ logger.debug("ssh #{@ssh_user}@#{ip}: ESTABLISHED")
+ break
+ rescue => e
+ logger.debug("ssh start #{@ssh_user}@#{ip} failed: #{e.inspect}")
+ sleep 1
+ end
+ end
+
+ @session.forward.remote(port, lo, port)
+ logger.info("`#{cmd}` started: OK")
+
+ Thread.new do
+ begin
+ @session.loop { true }
+ rescue IOError => e
+ logger.debug("`#{cmd}` terminated: #{e.inspect}")
+ @session = nil
+ end
+ end
+ end
+
+ end
+ end
+end
131 deployer/spec/assets/apply_spec_openstack.yml
View
@@ -0,0 +1,131 @@
+---
+deployment: micro
+release:
+ name: micro
+ version: 9
+properties:
+ micro: true
+ domain: vcap.me
+ env:
+ networks:
+ apps: local
+ management: local
+ nats:
+ user: nats
+ password: nats
+ address: 127.0.0.1
+ port: 4222
+ redis:
+ address: 127.0.0.1
+ port: 25255
+ password: redis
+ postgres:
+ user: postgres
+ password: postgres
+ address: 127.0.0.1
+ port: 5432
+ database: bosh
+ blobstore:
+ address: 127.0.0.1
+ backend_port: 25251
+ port: 25250
+ director:
+ user: director
+ password: director
+ agent:
+ user: agent
+ password: agent
+ director:
+ address: 127.0.0.1
+ name: micro
+ port: 25555
+ openstack_registry:
+ http:
+ port: 25778
+ user: admin
+ password: admin
+ db:
+ database: postgres://postgres:postgres@localhost/bosh
+ max_connections: 32
+ pool_timeout: 10
+ openstack:
+ auth_url: http://127.0.0.1:5000/v2.0/tokens
+ username: foo-key
+ api_key: foo-secret
+ tenant: foo-key
+ hm:
+ http:
+ port: 25923
+ user: hm
+ password: hm
+ loglevel: info
+ director_account:
+ user: admin
+ password: admin
+ intervals:
+ poll_director: 60
+ poll_grace_period: 30
+ log_stats: 300
+ analyze_agents: 60
+ agent_timeout: 180
+ rogue_agent_alert: 180
+index: 0
+packages:
+ ruby:
+ name: ruby
+ version: 0.1-dev
+ sha1: ecdbdf4dedcf4e521763e7a2d6c0b9194e5c5ed0
+ blobstore_id: d0c7a54f-184f-4e5e-b863-35d06bbae678
+ nats:
+ name: nats
+ version: 0.1-dev
+ sha1: ebd7b3d3bdf4590de9f5e4f4eadc819b34f56901
+ blobstore_id: c15172b6-965e-49bf-bea6-2e4322a7dc02
+ redis:
+ name: redis
+ version: 0.1-dev
+ sha1: 105e225be4569e8a4b9ab9dae92263f72fe906f2
+ blobstore_id: 4c8aac83-4f5d-41ef-85f7-d371c779d7f1
+ libpq:
+ name: libpq
+ version: 0.1-dev
+ sha1: 13e95edc074553c02b558bdaf91ee8ba976b3c4a
+ blobstore_id: 50dd33cd-66a1-4fc6-b304-f1e1ea7c1d5a
+ postgres:
+ name: postgres
+ version: 0.1-dev
+ sha1: d8b620fe4ef8076cc404af213909f3108572c308
+ blobstore_id: e17ef61e-12f5-4bf5-99f7-b26d32911238
+ blobstore:
+ name: blobstore
+ version: 0.1-dev
+ sha1: 73f5451871a9625d49636cd806e96483c3cc83f4
+ blobstore_id: 82709f56-d487-458f-9d96-0f5254cae09e
+ nginx:
+ name: nginx
+ version: 0.1-dev
+ sha1: 7b1fd58b4981aad05a630a387b7d858c6ea3c75b
+ blobstore_id: 1611cb73-da3b-4dea-bcb1-80c217c96b22
+ director:
+ name: director
+ version: 0.2-dev
+ sha1: f7d99e12ac65c4529db0b14d3b71e996bc2bc671
+ blobstore_id: bdeff591-daaa-4a6b-a452-c37db8e913c0
+ openstack_registry:
+ name: openstack_registry
+ version: 0.1-dev
+ sha1: 4c73b808faff4bbb959aeca9bb84ebe4a140d62b
+ blobstore_id: 4082220e-acf6-427c-b0fb-56c8b47aae0c
+ health_monitor:
+ name: health_monitor
+ version: 0.1-dev
+ sha1: 25bc4ef890649a446f33a667667b9df8038b012c
+ blobstore_id: 71250e09-a863-4b9c-8d59-831e37490584
+configuration_hash: {}
+
+job:
+ name: micro
+ version: 0.3-dev
+ sha1: 6df1470e27be9e80cc476823d0a71b1790f2620b
+ template: micro
+ blobstore_id: a44be400-a055-4670-926d-dfae70d3218d
0  deployer/spec/assets/openstack_registry
View
No changes.
24 deployer/spec/assets/test-bootstrap-config-openstack.yml
View
@@ -0,0 +1,24 @@
+---
+name: bosh-bootstrap-openstack
+
+network:
+ type: dynamic
+
+env:
+ bosh:
+ password: $6$salt$password
+
+cloud:
+ plugin: openstack
+ properties:
+ openstack:
+ auth_url: http://127.0.0.1:5000/v2.0/tokens
+ username: foo-key
+ api_key: foo-secret
+ tenant: foo-key
+ default_key_name: foo-key
+ default_security_groups: ["quick-start-1"]
+ registry:
+ endpoint: http://admin:admin@10.176.194.184:25695
+ user: admin
+ password: admin
93 deployer/spec/unit/openstack/config_spec.rb
View
@@ -0,0 +1,93 @@
+# Copyright (c) 2009-2012 VMware, Inc.
+
+require File.expand_path("../../../spec_helper", __FILE__)
+require 'fog'
+
+describe Bosh::Deployer::Config do
+ before(:each) do
+ @dir = Dir.mktmpdir("bdc_spec")
+ end
+
+ after(:each) do
+ FileUtils.remove_entry_secure @dir
+ end
+
+ it "configure should fail without cloud properties" do
+ lambda {
+ Bosh::Deployer::Config.configure({"dir" => @dir})
+ }.should raise_error(Bosh::Deployer::ConfigError)
+ end
+
+ it "should default agent properties" do
+ config = YAML.load_file(spec_asset("test-bootstrap-config-openstack.yml"))
+ config["dir"] = @dir
+ Bosh::Deployer::Config.configure(config)
+
+ properties = Bosh::Deployer::Config.cloud_options["properties"]
+ properties["agent"].should be_kind_of(Hash)
+ properties["agent"]["mbus"].start_with?("http://").should be_true
+ properties["agent"]["blobstore"].should be_kind_of(Hash)
+ end
+
+ it "should map network properties" do
+ config = YAML.load_file(spec_asset("test-bootstrap-config-openstack.yml"))
+ config["dir"] = @dir
+ Bosh::Deployer::Config.configure(config)
+
+ networks = Bosh::Deployer::Config.networks
+ networks.should be_kind_of(Hash)
+
+ net = networks['bosh']
+ net.should be_kind_of(Hash)
+ ['cloud_properties', 'type'].each do |key|
+ net[key].should_not be_nil
+ end
+ end
+
+ it "should default vm env properties" do
+ env = Bosh::Deployer::Config.env
+ env.should be_kind_of(Hash)
+ env.should have_key("bosh")
+ env["bosh"].should be_kind_of(Hash)
+ env["bosh"]["password"].should_not be_nil
+ env["bosh"]["password"].should be_kind_of(String)
+ env["bosh"]["password"].should == "$6$salt$password"
+ end
+
+ it "should contain default vm resource properties" do
+ Bosh::Deployer::Config.configure({"dir" => @dir, "cloud" => { "plugin" => "openstack" }})
+ resources = Bosh::Deployer::Config.resources
+ resources.should be_kind_of(Hash)
+
+ resources['persistent_disk'].should be_kind_of(Integer)
+
+ cloud_properties = resources['cloud_properties']
+ cloud_properties.should be_kind_of(Hash)
+
+ ['instance_type'].each do |key|
+ cloud_properties[key].should_not be_nil
+ end
+ end
+
+ it "should configure agent using mbus property" do
+ config = YAML.load_file(spec_asset("test-bootstrap-config-openstack.yml"))
+ config["dir"] = @dir
+ Bosh::Deployer::Config.configure(config)
+ agent = Bosh::Deployer::Config.agent
+ agent.should be_kind_of(Bosh::Agent::HTTPClient)
+ end
+
+ it "should have openstack and registry object access" do
+ config = YAML.load_file(spec_asset("test-bootstrap-config-openstack.yml"))
+ config["dir"] = @dir
+ Bosh::Deployer::Config.configure(config)
+ openstack = double(Fog::Compute)
+ Fog::Compute.stub(:new).and_return(openstack)
+ glance = double(Fog::Image)
+ Fog::Image.stub(:new).and_return(glance)
+ cloud = Bosh::Deployer::Config.cloud
+ cloud.respond_to?(:openstack).should be_true
+ cloud.respond_to?(:registry).should be_true
+ cloud.registry.should be_kind_of(Bosh::OpenStackCloud::RegistryClient)
+ end
+end
217 deployer/spec/unit/openstack/instance_manager_spec.rb
View
@@ -0,0 +1,217 @@
+# Copyright (c) 2009-2012 VMware, Inc.
+
+require File.expand_path("../../../spec_helper", __FILE__)
+
+BOSH_STEMCELL_TGZ ||= "bosh-instance-1.0.tgz"
+
+describe Bosh::Deployer::InstanceManager do
+ before(:each) do
+ @dir = Dir.mktmpdir("bdim_spec")
+ @config = YAML.load_file(spec_asset("test-bootstrap-config-openstack.yml"))
+ @config["dir"] = @dir
+ @config["name"] = "spec-#{UUIDTools::UUID.random_create.to_s}"
+ @config["logging"] = { "file" => "#{@dir}/bmim.log" }
+ @deployer = Bosh::Deployer::InstanceManager.create(@config)
+ @cloud = mock("cloud")
+ @openstack = mock("openstack")
+ @cloud.stub(:openstack).and_return(@openstack)
+ Bosh::Deployer::Config.stub!(:cloud).and_return(@cloud)
+ @agent = mock("agent")
+ Bosh::Deployer::Config.stub!(:agent).and_return(@agent)
+ end
+
+ after(:each) do
+ @deployer.state.destroy
+ FileUtils.remove_entry_secure @dir
+ end
+
+ def load_deployment
+ @deployer.send(:load_deployments)["instances"].select { |d| d[:name] == @deployer.state.name }.first
+ end
+
+ def discover_bosh_ip(ip, id)
+ server = mock("server")
+ servers = mock("servers")
+ @openstack.should_receive(:servers).and_return(servers)
+ servers.should_receive(:get).with(id).and_return(server)
+ server.should_receive(:public_ip_address).and_return(ip)
+ end
+
+ it "should update the apply spec" do
+ dummy_ip = "1.2.3.4"
+ @deployer.stub!(:service_ip).and_return(dummy_ip)
+ spec = YAML.load_file(spec_asset("apply_spec_openstack.yml"))
+ @deployer.update_spec(spec)
+ props = spec["properties"]
+
+ %w{blobstore postgres director redis nats openstack_registry}.each do |service|
+ ip = props[service]["address"]
+ ip.should_not be_nil
+ ip.should_not == "127.0.0.1"
+ ip.should == dummy_ip
+ end
+ end
+
+ it "should apply" do
+ @deployer.stub!(:service_ip).and_return("10.0.0.10")
+ spec = YAML.load_file(spec_asset("apply_spec_openstack.yml"))
+ updated_spec = @deployer.update_spec(spec.dup)
+ @agent.should_receive(:run_task).with(:stop)
+ @agent.should_receive(:run_task).with(:apply, updated_spec)
+ @agent.should_receive(:run_task).with(:start)
+ @deployer.apply(spec)
+ end
+
+ it "should not populate disk model" do
+ disk_model = @deployer.disk_model
+ disk_model.should == nil
+ end
+
+ it "should create a Bosh instance" do
+ @deployer.stub!(:service_ip).and_return("10.0.0.10")
+ spec = YAML.load_file(spec_asset("apply_spec_openstack.yml"))
+ @deployer.stub!(:run_command)
+ @deployer.stub!(:wait_until_agent_ready)
+ @deployer.stub!(:wait_until_director_ready)
+ @deployer.stub!(:load_apply_spec).and_return(spec)
+ @deployer.stub!(:load_stemcell_manifest).and_return({"cloud_properties" => {}})
+
+ @deployer.state.uuid.should_not be_nil
+
+ @deployer.state.stemcell_cid.should be_nil
+ @deployer.state.vm_cid.should be_nil
+
+ @cloud.should_receive(:create_stemcell).and_return("SC-CID-CREATE")
+ @cloud.should_receive(:create_vm).and_return("VM-CID-CREATE")
+ @cloud.should_receive(:create_disk).and_return("DISK-CID-CREATE")
+ @cloud.should_receive(:attach_disk).with("VM-CID-CREATE", "DISK-CID-CREATE")
+ @agent.should_receive(:run_task).with(:mount_disk, "DISK-CID-CREATE").and_return({})
+ @agent.should_receive(:run_task).with(:stop)
+ @agent.should_receive(:run_task).with(:apply, spec)
+ @agent.should_receive(:run_task).with(:start)
+
+ discover_bosh_ip("10.0.0.1", "VM-CID-CREATE")
+ @deployer.create(BOSH_STEMCELL_TGZ)
+
+ @deployer.state.stemcell_cid.should == "SC-CID-CREATE"
+ @deployer.state.vm_cid.should == "VM-CID-CREATE"
+ @deployer.state.disk_cid.should == "DISK-CID-CREATE"
+ load_deployment.should == @deployer.state.values
+
+ @deployer.renderer.total.should == @deployer.renderer.index
+ end
+
+ it "should destroy a Bosh instance" do
+ disk_cid = "33"
+ @deployer.state.disk_cid = disk_cid
+ @deployer.state.stemcell_cid = "SC-CID-DESTROY"
+ @deployer.state.stemcell_name = @deployer.state.stemcell_cid
+
+ @deployer.state.vm_cid = "VM-CID-DESTROY"
+
+ @agent.should_receive(:list_disk).and_return([disk_cid])
+ @agent.should_receive(:run_task).with(:stop)
+ @agent.should_receive(:run_task).with(:unmount_disk, disk_cid).and_return({})
+ @cloud.should_receive(:detach_disk).with("VM-CID-DESTROY", disk_cid)
+ @cloud.should_receive(:delete_disk).with(disk_cid)
+ @cloud.should_receive(:delete_vm).with("VM-CID-DESTROY")
+
+ @deployer.destroy
+
+ @deployer.state.stemcell_cid.should be_nil
+ @deployer.state.stemcell_name.should be_nil
+ @deployer.state.vm_cid.should be_nil
+ @deployer.state.disk_cid.should be_nil
+
+ load_deployment.should == @deployer.state.values
+
+ @deployer.renderer.total.should == @deployer.renderer.index
+ end
+
+ it "should update a Bosh instance" do
+ @deployer.stub!(:service_ip).and_return("10.0.0.10")
+ spec = YAML.load_file(spec_asset("apply_spec_openstack.yml"))
+ disk_cid = "22"
+ @deployer.stub!(:run_command)
+ @deployer.stub!(:wait_until_agent_ready)
+ @deployer.stub!(:wait_until_director_ready)
+ @deployer.stub!(:load_apply_spec).and_return(spec)
+ @deployer.stub!(:load_stemcell_manifest).and_return({"cloud_properties" => {}})
+ @deployer.stub!(:persistent_disk_changed?).and_return(false)
+
+ @deployer.state.stemcell_cid = "SC-CID-UPDATE"
+ @deployer.state.vm_cid = "VM-CID-UPDATE"
+ @deployer.state.disk_cid = disk_cid
+
+ @agent.should_receive(:run_task).with(:stop)
+ @agent.should_receive(:run_task).with(:unmount_disk, disk_cid).and_return({})
+ @cloud.should_receive(:detach_disk).with("VM-CID-UPDATE", disk_cid)
+ @cloud.should_receive(:delete_vm).with("VM-CID-UPDATE")
+ @cloud.should_receive(:delete_stemcell).with("SC-CID-UPDATE")
+ @cloud.should_receive(:create_stemcell).and_return("SC-CID")
+ @cloud.should_receive(:create_vm).and_return("VM-CID")
+ @cloud.should_receive(:attach_disk).with("VM-CID", disk_cid)
+ @agent.should_receive(:run_task).with(:mount_disk, disk_cid).and_return({})
+ @agent.should_receive(:list_disk).and_return([disk_cid])
+ @agent.should_receive(:run_task).with(:stop)
+ @agent.should_receive(:run_task).with(:apply, spec)
+ @agent.should_receive(:run_task).with(:start)
+
+ discover_bosh_ip("10.0.0.2", "VM-CID")
+ @deployer.update(BOSH_STEMCELL_TGZ)
+
+ @deployer.state.stemcell_cid.should == "SC-CID"
+ @deployer.state.vm_cid.should == "VM-CID"
+ @deployer.state.disk_cid.should == disk_cid
+
+ load_deployment.should == @deployer.state.values
+ end
+
+ it "should fail to create a Bosh instance if stemcell CID exists" do
+ @deployer.state.stemcell_cid = "SC-CID"
+
+ lambda {
+ @deployer.create(BOSH_STEMCELL_TGZ)
+ }.should raise_error(Bosh::Deployer::ConfigError)
+ end
+
+ it "should fail to create a Bosh instance if VM CID exists" do
+ @deployer.state.vm_cid = "VM-CID"
+
+ lambda {
+ @deployer.create(BOSH_STEMCELL_TGZ)
+ }.should raise_error(Bosh::Deployer::ConfigError)
+ end
+
+ it "should fail to destroy a Bosh instance unless stemcell CID exists" do
+ @deployer.state.vm_cid = "VM-CID"
+ @agent.should_receive(:run_task).with(:stop)
+ @cloud.should_receive(:delete_vm).with("VM-CID")
+ lambda {
+ @deployer.destroy
+ }.should raise_error(Bosh::Deployer::ConfigError)
+ end
+
+ it "should fail to destroy a Bosh instance unless VM CID exists" do
+ @deployer.state.stemcell_cid = "SC-CID"
+ @agent.should_receive(:run_task).with(:stop)
+ lambda {
+ @deployer.destroy
+ }.should raise_error(Bosh::Deployer::ConfigError)
+ end
+
+ require 'deployer/instance_manager/openstack'
+
+ internal_to Bosh::Deployer::InstanceManager::Openstack do
+ it "should not find openstack_registry" do
+ path = "/usr/bin:/bin"
+ @deployer.has_openstack_registry?(path).should be_false
+ end
+
+ it "should find find openstack_registry" do
+ path = ENV['PATH']
+ path += ":#{File.dirname(spec_asset('openstack_registry'))}"
+ @deployer.has_openstack_registry?(path).should be_true
+ end
+ end
+end
BIN  deployer/vendor/cache/bosh_openstack_cpi-0.0.2.gem
View
Binary file not shown
BIN  deployer/vendor/cache/excon-0.14.3.gem
View
Binary file not shown
BIN  deployer/vendor/cache/fog-1.4.0.gem
View
Binary file not shown
BIN  deployer/vendor/cache/formatador-0.2.3.gem
View
Binary file not shown
BIN  deployer/vendor/cache/httparty-0.8.1.gem
View
Binary file not shown
BIN  deployer/vendor/cache/httparty-0.8.3.gem
View
Binary file not shown
BIN  deployer/vendor/cache/json-1.6.6.gem
View
Binary file not shown
BIN  deployer/vendor/cache/json-1.7.3.gem
View
Binary file not shown
BIN  deployer/vendor/cache/multi_xml-0.4.2.gem
View
Binary file not shown
BIN  deployer/vendor/cache/multi_xml-0.5.1.gem
View
Binary file not shown
BIN  deployer/vendor/cache/nokogiri-1.5.2.gem
View
Binary file not shown
BIN  deployer/vendor/cache/nokogiri-1.5.5.gem
View
Binary file not shown
BIN  deployer/vendor/cache/sequel-3.33.0.gem
View
Binary file not shown
BIN  deployer/vendor/cache/sequel-3.37.0.gem
View
Binary file not shown
BIN  deployer/vendor/cache/sqlite3-1.3.5.gem
View
Binary file not shown
BIN  deployer/vendor/cache/sqlite3-1.3.6.gem
View
Binary file not shown
Please sign in to comment.
Something went wrong with that request. Please try again.