dopv 0.11.0

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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/ChangeLog.md +456 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +260 -0
  7. data/Guardfile +22 -0
  8. data/LICENSE.txt +177 -0
  9. data/README.md +214 -0
  10. data/Rakefile +6 -0
  11. data/bin/dopv +4 -0
  12. data/dopv.gemspec +52 -0
  13. data/lib/dopv.rb +166 -0
  14. data/lib/dopv/cli.rb +54 -0
  15. data/lib/dopv/cli/command_add.rb +37 -0
  16. data/lib/dopv/cli/command_export.rb +26 -0
  17. data/lib/dopv/cli/command_import.rb +32 -0
  18. data/lib/dopv/cli/command_list.rb +18 -0
  19. data/lib/dopv/cli/command_remove.rb +29 -0
  20. data/lib/dopv/cli/command_run.rb +38 -0
  21. data/lib/dopv/cli/command_update.rb +35 -0
  22. data/lib/dopv/cli/command_validate.rb +30 -0
  23. data/lib/dopv/infrastructure.rb +40 -0
  24. data/lib/dopv/infrastructure/providers/baremetal.rb +12 -0
  25. data/lib/dopv/infrastructure/providers/base.rb +422 -0
  26. data/lib/dopv/infrastructure/providers/openstack.rb +308 -0
  27. data/lib/dopv/infrastructure/providers/ovirt.rb +228 -0
  28. data/lib/dopv/infrastructure/providers/vsphere.rb +322 -0
  29. data/lib/dopv/log.rb +14 -0
  30. data/lib/dopv/persistent_disk.rb +128 -0
  31. data/lib/dopv/plan.rb +17 -0
  32. data/lib/dopv/state_store.rb +87 -0
  33. data/lib/dopv/version.rb +3 -0
  34. data/spec/data/hooks/test_hook_script_1 +9 -0
  35. data/spec/data/hooks/test_hook_script_2 +10 -0
  36. data/spec/data/plans/test-plan-1.yaml +140 -0
  37. data/spec/spec_helper.rb +112 -0
  38. data/spec/unit/dopv/dopv_spec.rb +7 -0
  39. data/spec/unit/dopv/persistent_disk_spec.rb +38 -0
  40. data/spec/unit/dopv/plan_spec.rb +34 -0
  41. data/spec/unit/dopv/version_spec.rb +17 -0
  42. metadata +401 -0
@@ -0,0 +1,17 @@
1
+ require 'forwardable'
2
+ require 'yaml'
3
+ require 'dop_common'
4
+
5
+ module Dopv
6
+ class Plan
7
+ extend Forwardable
8
+
9
+ attr_reader :plan_parser
10
+
11
+ def_delegators :@plan_parser, :name, :nodes, :max_in_flight, :valid?
12
+
13
+ def initialize(plan_parser)
14
+ @plan_parser = plan_parser
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,87 @@
1
+ #
2
+ # This is the DOPv disk state store
3
+ #
4
+ module Dopv
5
+ class StateStore
6
+
7
+ def initialize(plan_name, plan_store)
8
+ @plan_store = plan_store
9
+ @plan_name = plan_name
10
+ @state_store = @plan_store.state_store(plan_name, 'dopv')
11
+ end
12
+
13
+ def update(options = {})
14
+ if options[:clear]
15
+ clear(options)
16
+ elsif options[:ignore]
17
+ ignore(options)
18
+ else
19
+ update_state(options)
20
+ end
21
+ rescue DopCommon::UnknownVersionError => e
22
+ Dopv.log.warn("The state had an unknown plan version #{e.message}")
23
+ Dopv.log.warn("Bumping state to most recent version")
24
+ ignore(options)
25
+ rescue => e
26
+ Dopv.log.error("An error occured during update: #{e.message}")
27
+ Dopv.log.error("Please update with the 'clear' or 'ignore' option")
28
+ end
29
+
30
+ def export
31
+ @state_store.transaction(true) do
32
+ @state_store[:data_volumes] || {}
33
+ end
34
+ end
35
+
36
+ def import(data_volumes)
37
+ @state_store.transaction do
38
+ @state_store[:data_volumes] = data_volumes
39
+ end
40
+ end
41
+
42
+ def method_missing(m, *args, &block)
43
+ @state_store.send(m, *args, &block)
44
+ end
45
+
46
+ private
47
+
48
+ def clear(options)
49
+ @state_store.transaction do
50
+ Dopv.log.debug("Clearing the disk state for plan #{@plan_name}")
51
+ ver = @plan_store.show_versions(@plan_name).last
52
+ @state_store[:data_volumes] = {}
53
+ @state_store[:version] = ver
54
+ end
55
+ end
56
+
57
+ def ignore(options)
58
+ @state_store.transaction do
59
+ ver = @plan_store.show_versions(@plan_name).last
60
+ Dopv.log.debug("Ignoring update and setting disk state version of plan #{@plan_name} to #{ver}")
61
+ @state_store[:version] = ver
62
+ end
63
+ end
64
+
65
+ def update_state(options)
66
+ @state_store.update do |plan_diff|
67
+ Dopv.log.debug("Updating disk state for plan #{@plan_name}. This is the diff:")
68
+ Dopv.log.debug(plan_diff.to_s)
69
+ #TODO: Add update logic for plan updates here
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ class StateStoreObserver
76
+
77
+ def initialize(plan, state_store)
78
+ @plan = plan
79
+ @state_store = state_store
80
+ end
81
+
82
+ def update(notify_only = false)
83
+ @state_store.persist_state(@plan)
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module Dopv
2
+ VERSION = '0.11.0'
3
+ end
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+
3
+ echo "This is a testing hook #1"
4
+ echo "Nodename: ${1}"
5
+ echo "Change flag: ${2}"
6
+
7
+ env
8
+
9
+ exit 0
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ echo "This is a testing hook #2"
4
+ echo "Nodename: ${1}"
5
+ echo "Change flag: ${2}"
6
+
7
+ env
8
+
9
+ echo "Trying to list a non-existent directory"
10
+ ls -la /non-existent
@@ -0,0 +1,140 @@
1
+ name: test-1
2
+ max_in_flight: 5
3
+
4
+ credentials:
5
+ api_login_ovirt:
6
+ type: username_password
7
+ username: foo@bar
8
+ password: foobar
9
+ deployment_login:
10
+ type: username_password
11
+ username: root
12
+ password: baz
13
+
14
+ infrastructures:
15
+ test-1:
16
+ type: ovirt
17
+ endpoint: https://foo.bar.baz/api
18
+ credentials: api_login_ovirt
19
+ networks:
20
+ net-1:
21
+ ip_pool:
22
+ from: 192.168.0.10
23
+ to: 192.168.0.245
24
+ ip_netmask: 255.255.255.0
25
+ ip_defgw: 192.168.0.254
26
+ net-2:
27
+ ip_pool:
28
+ from: 192.168.1.10
29
+ to: 192.168.1.245
30
+ ip_netmask: 255.255.255.0
31
+ ip_defgw: 192.168.1.254
32
+ affinity_groups:
33
+ test-1:
34
+ positive: true
35
+ enforce: false
36
+ cluster: test-1
37
+
38
+ hooks:
39
+ pre_create_vm:
40
+ - spec/data/hooks/test_hook_script_1
41
+ - spec/data/hooks/test_hook_script_2
42
+ post_create_vm:
43
+ - spec/data/hooks/test_hook_script_1
44
+ - spec/data/hooks/test_hook_script_2
45
+ pre_destroy_vm:
46
+ - spec/data/hooks/test_hook_script_1
47
+ - spec/data/hooks/test_hook_script_2
48
+ post_destroy_vm:
49
+ - spec/data/hooks/test_hook_script_1
50
+ - spec/data/hooks/test_hook_script_2
51
+
52
+ nodes:
53
+ test-1.foo.bar.baz:
54
+ infrastructure: test-1
55
+ infrastructure_properties:
56
+ datacenter: test-1
57
+ cluster: test-1
58
+ keep_ha: false
59
+ affinity_groups:
60
+ - test-1
61
+ full_clone: false
62
+ image: img-1
63
+ interfaces:
64
+ eth0:
65
+ network: net-1
66
+ ip: 192.168.0.11
67
+ eth1:
68
+ network: net-2
69
+ ip: dhcp
70
+ set_gateway: false
71
+ disks:
72
+ disk-1:
73
+ pool: test-1
74
+ size: 1G
75
+ disk-2:
76
+ pool: test-2
77
+ size: 2G
78
+ thin: false
79
+ dns:
80
+ name_servers:
81
+ - 192.168.1.254
82
+ search_domains:
83
+ - foo.bar.baz
84
+ cores: 3
85
+ memory: 6G
86
+ credentials:
87
+ - deployment_login
88
+ test-2.foo.bar.baz:
89
+ infrastructure: test-1
90
+ infrastructure_properties:
91
+ datacenter: test-1
92
+ cluster: test-1
93
+ keep_ha: false
94
+ affinity_groups:
95
+ - test-1
96
+ full_clone: false
97
+ image: img-2
98
+ interfaces:
99
+ eth0:
100
+ network: net-1
101
+ ip: 192.168.0.12
102
+ disks:
103
+ disk-1:
104
+ pool: test-3
105
+ size: 1G
106
+ dns:
107
+ name_servers:
108
+ - 192.168.1.254
109
+ search_domains:
110
+ - foo.bar.baz
111
+ flavor: small
112
+ credentials:
113
+ - deployment_login
114
+
115
+ steps:
116
+ default:
117
+ - name: '0 - 1: ALL: Configure ssh login credentials'
118
+ nodes: all
119
+ max_in_flight: -1
120
+ set_plugin_defaults:
121
+ - plugins: "/^ssh/"
122
+ :credentials: deployment_login
123
+ command:
124
+ plugin: dummy
125
+ - name: '0 - 2: ALL: Make sure we can login to all nodes'
126
+ nodes: all
127
+ max_in_flight: -1
128
+ command:
129
+ plugin: ssh/wait_for_login
130
+ plugin_timeout: 600
131
+ - name: '0 - 3: ALL: Disable puppet to prevent automatic runs'
132
+ nodes: all
133
+ max_in_flight: -1
134
+ command:
135
+ plugin: ssh/custom
136
+ exec: |
137
+ echo "Dopi was here" > /tmp/dopi.txt
138
+ verify_commands:
139
+ - plugin: ssh/file_exists
140
+ file: "/tmp/dopi.txt"
@@ -0,0 +1,112 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ add_filter '/.bundle/'
5
+ add_filter '/vendor/'
6
+ end
7
+
8
+ require 'dopv'
9
+
10
+ # This file was generated by the `rspec --init` command. Conventionally, all
11
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
12
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
13
+ # this file to always be loaded, without a need to explicitly require it in any
14
+ # files.
15
+ #
16
+ # Given that it is always loaded, you are encouraged to keep this file as
17
+ # light-weight as possible. Requiring heavyweight dependencies from this file
18
+ # will add to the boot time of your test suite on EVERY test run, even for an
19
+ # individual file that may not need all of that loaded. Instead, consider making
20
+ # a separate helper file that requires the additional dependencies and performs
21
+ # the additional setup, and require it from the spec files that actually need
22
+ # it.
23
+ #
24
+ # The `.rspec` file also contains a few flags that are not defaults but that
25
+ # users commonly want.
26
+ #
27
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
28
+ RSpec.configure do |config|
29
+ # rspec-expectations config goes here. You can use an alternate
30
+ # assertion/expectation library such as wrong or the stdlib/minitest
31
+ # assertions if you prefer.
32
+ config.expect_with :rspec do |expectations|
33
+ # This option will default to `true` in RSpec 4. It makes the `description`
34
+ # and `failure_message` of custom matchers include text for helper methods
35
+ # defined using `chain`, e.g.:
36
+ # be_bigger_than(2).and_smaller_than(4).description
37
+ # # => "be bigger than 2 and smaller than 4"
38
+ # ...rather than:
39
+ # # => "be bigger than 2"
40
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
41
+ end
42
+
43
+ # rspec-mocks config goes here. You can use an alternate test double
44
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
45
+ config.mock_with :rspec do |mocks|
46
+ # Prevents you from mocking or stubbing a method that does not exist on
47
+ # a real object. This is generally recommended, and will default to
48
+ # `true` in RSpec 4.
49
+ mocks.verify_partial_doubles = true
50
+ end
51
+
52
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
53
+ # have no way to turn it off -- the option exists only for backwards
54
+ # compatibility in RSpec 3). It causes shared context metadata to be
55
+ # inherited by the metadata hash of host groups and examples, rather than
56
+ # triggering implicit auto-inclusion in groups with matching metadata.
57
+ config.shared_context_metadata_behavior = :apply_to_host_groups
58
+
59
+ # The settings below are suggested to provide a good initial experience
60
+ # with RSpec, but feel free to customize to your heart's content.
61
+ =begin
62
+ # This allows you to limit a spec run to individual examples or groups
63
+ # you care about by tagging them with `:focus` metadata. When nothing
64
+ # is tagged with `:focus`, all examples get run. RSpec also provides
65
+ # aliases for `it`, `describe`, and `context` that include `:focus`
66
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
67
+ config.filter_run_when_matching :focus
68
+
69
+ # Allows RSpec to persist some state between runs in order to support
70
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
71
+ # you configure your source control system to ignore this file.
72
+ config.example_status_persistence_file_path = "spec/examples.txt"
73
+
74
+ # Limits the available syntax to the non-monkey patched syntax that is
75
+ # recommended. For more details, see:
76
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
77
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
78
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
79
+ config.disable_monkey_patching!
80
+
81
+ # This setting enables warnings. It's recommended, but in some cases may
82
+ # be too noisy due to issues in dependencies.
83
+ config.warnings = true
84
+
85
+ # Many RSpec users commonly either run the entire suite or an individual
86
+ # file, and it's useful to allow more verbose output when running an
87
+ # individual spec file.
88
+ if config.files_to_run.one?
89
+ # Use the documentation formatter for detailed output,
90
+ # unless a formatter has already been configured
91
+ # (e.g. via a command-line flag).
92
+ config.default_formatter = 'doc'
93
+ end
94
+
95
+ # Print the 10 slowest examples and example groups at the
96
+ # end of the spec run, to help surface which specs are running
97
+ # particularly slow.
98
+ config.profile_examples = 10
99
+
100
+ # Run specs in random order to surface order dependencies. If you find an
101
+ # order dependency and want to debug it, you can fix the order by providing
102
+ # the seed, which is printed after each run.
103
+ # --seed 1234
104
+ config.order = :random
105
+
106
+ # Seed global randomization in this process using the `--seed` CLI option.
107
+ # Setting this allows you to use `--seed` to deterministically reproduce
108
+ # test failures related to randomization by passing the same `--seed` value
109
+ # as the one that triggered the failure.
110
+ Kernel.srand config.seed
111
+ =end
112
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dopv do
4
+ it 'should be a module' do
5
+ expect(Dopv).to be_kind_of(Module)
6
+ end
7
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
+
4
+ describe Dopv::PersistentDisk::Entry do
5
+ before(:each) do
6
+ @disk_valid = {
7
+ :name => 'disk-1',
8
+ :id => SecureRandom.uuid,
9
+ :pool => 'pool-1',
10
+ :node => 'foo.bar.baz',
11
+ :size => 1024*1024*1024
12
+ }
13
+ @entry = Dopv::PersistentDisk::Entry.new(@disk_valid)
14
+ end
15
+
16
+ describe '#new' do
17
+ it 'creates a new entry object from proper input' do
18
+ expect(@entry).to be_an_instance_of(Dopv::PersistentDisk::Entry)
19
+ end
20
+
21
+ it 'will raise an exception if input is incorrect' do
22
+ expect { Dopv::PersistentDisk::Entry.new({}) }.to \
23
+ raise_error(Dopv::PersistentDisk::PersistentDiskError)
24
+ end
25
+ end
26
+
27
+ %w(name id pool size node).each do |accessor|
28
+ describe "##{accessor}" do
29
+ it "responds to #{accessor}" do
30
+ expect(@entry.respond_to?(:"#{accessor}")).to be true
31
+ end
32
+
33
+ it "returns entry's #{accessor}" do
34
+ expect(@entry.send(:"#{accessor}")).to eq @disk_valid[:"#{accessor}"]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'yaml'
3
+
4
+ describe Dopv::Plan do
5
+ before(:each) do
6
+ plan_file = 'spec/data/plans/test-plan-1.yaml'
7
+ plan_parser = DopCommon::Plan.new(YAML.load_file(plan_file))
8
+ @plan = Dopv::Plan.new(plan_parser)
9
+ end
10
+
11
+ describe '#new' do
12
+ it 'should create a plan object' do
13
+ expect(@plan).to be_a Dopv::Plan
14
+ end
15
+ end
16
+
17
+ describe '#name' do
18
+ it 'is called test-1' do
19
+ expect(@plan.name).to eq 'test-1'
20
+ end
21
+ end
22
+
23
+ describe '#nodes' do
24
+ it 'creates two nodes' do
25
+ expect(@plan.nodes.length).to eq 2
26
+ end
27
+ end
28
+
29
+ describe '#valid?' do
30
+ it 'is a valid plan' do
31
+ expect(@plan.valid?).to eq true
32
+ end
33
+ end
34
+ end