puppetfactory 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +13 -0
  3. data/README.md +0 -0
  4. data/bin/pfsh +31 -0
  5. data/bin/puppetfactory +153 -0
  6. data/lib/puppetfactory.rb +300 -0
  7. data/lib/puppetfactory/cli.rb +114 -0
  8. data/lib/puppetfactory/dashboard/rake_tasks.rb +69 -0
  9. data/lib/puppetfactory/dashboard/serverspec_helper.rb +84 -0
  10. data/lib/puppetfactory/dashboard/spec_helper.rb +26 -0
  11. data/lib/puppetfactory/helpers.rb +37 -0
  12. data/lib/puppetfactory/monkeypatches.rb +30 -0
  13. data/lib/puppetfactory/plugins.rb +11 -0
  14. data/lib/puppetfactory/plugins/certificates.rb +28 -0
  15. data/lib/puppetfactory/plugins/classification.rb +75 -0
  16. data/lib/puppetfactory/plugins/code_manager.rb +156 -0
  17. data/lib/puppetfactory/plugins/console_user.rb +62 -0
  18. data/lib/puppetfactory/plugins/dashboard.rb +128 -0
  19. data/lib/puppetfactory/plugins/docker.rb +193 -0
  20. data/lib/puppetfactory/plugins/example.rb +88 -0
  21. data/lib/puppetfactory/plugins/github.rb +102 -0
  22. data/lib/puppetfactory/plugins/gitlab.rb +62 -0
  23. data/lib/puppetfactory/plugins/hooks.rb +46 -0
  24. data/lib/puppetfactory/plugins/login_shell.rb +10 -0
  25. data/lib/puppetfactory/plugins/logs.rb +34 -0
  26. data/lib/puppetfactory/plugins/r10k.rb +112 -0
  27. data/lib/puppetfactory/plugins/shell_user.rb +69 -0
  28. data/lib/puppetfactory/plugins/user_environment.rb +77 -0
  29. data/public/dashboard.js +100 -0
  30. data/public/font-awesome/css/font-awesome.css +2199 -0
  31. data/public/font-awesome/css/font-awesome.min.css +4 -0
  32. data/public/font-awesome/fonts/FontAwesome.otf +0 -0
  33. data/public/font-awesome/fonts/fontawesome-webfont.eot +0 -0
  34. data/public/font-awesome/fonts/fontawesome-webfont.svg +685 -0
  35. data/public/font-awesome/fonts/fontawesome-webfont.ttf +0 -0
  36. data/public/font-awesome/fonts/fontawesome-webfont.woff +0 -0
  37. data/public/font-awesome/fonts/fontawesome-webfont.woff2 +0 -0
  38. data/public/gitviz/LICENSE.md +20 -0
  39. data/public/gitviz/README.md +13 -0
  40. data/public/gitviz/css/explaingit.css +227 -0
  41. data/public/gitviz/css/vendor/1140.css +130 -0
  42. data/public/gitviz/images/forkme_right_red_aa0000.png +0 -0
  43. data/public/gitviz/images/grippy-close.png +0 -0
  44. data/public/gitviz/images/grippy.png +0 -0
  45. data/public/gitviz/images/prompt.gif +0 -0
  46. data/public/gitviz/index.html +734 -0
  47. data/public/gitviz/js/controlbox.js +459 -0
  48. data/public/gitviz/js/explaingit.js +74 -0
  49. data/public/gitviz/js/historyview.js +979 -0
  50. data/public/gitviz/js/main.js +56 -0
  51. data/public/gitviz/js/vendor/d3.min.js +4 -0
  52. data/public/gitviz/js/vendor/jquery-latest.min.js +6 -0
  53. data/public/gitviz/js/vendor/normalize.css +396 -0
  54. data/public/gitviz/js/vendor/require.min.js +35 -0
  55. data/public/gitviz/memtest.html +44 -0
  56. data/public/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  57. data/public/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  58. data/public/images/ui-bg_flat_10_000000_40x100.png +0 -0
  59. data/public/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  60. data/public/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  61. data/public/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  62. data/public/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  63. data/public/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  64. data/public/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  65. data/public/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  66. data/public/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  67. data/public/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  68. data/public/images/ui-icons_222222_256x240.png +0 -0
  69. data/public/images/ui-icons_228ef1_256x240.png +0 -0
  70. data/public/images/ui-icons_454545_256x240.png +0 -0
  71. data/public/images/ui-icons_ef8c08_256x240.png +0 -0
  72. data/public/images/ui-icons_ffd27a_256x240.png +0 -0
  73. data/public/images/ui-icons_ffffff_256x240.png +0 -0
  74. data/public/jquery-1.11.1.min.js +4 -0
  75. data/public/jquery-ui.css +464 -0
  76. data/public/jquery-ui.min.css +7 -0
  77. data/public/jquery-ui.min.js +13 -0
  78. data/public/jquery-ui.structure.min.css +5 -0
  79. data/public/jquery-ui.theme.min.css +5 -0
  80. data/public/jquery.activity-indicator-1.0.0.min.js +10 -0
  81. data/public/jquery.js +9789 -0
  82. data/public/loginscripts.js +18 -0
  83. data/public/scripts.js +36 -0
  84. data/public/style.css +193 -0
  85. data/public/usermanagement.js +133 -0
  86. data/templates/init_scripts.erb +10 -0
  87. data/templates/puppet.conf.erb +10 -0
  88. data/templates/site.pp.erb +50 -0
  89. data/views/dashboard.erb +62 -0
  90. data/views/home.erb +43 -0
  91. data/views/index.erb +29 -0
  92. data/views/logs.erb +26 -0
  93. data/views/shell.erb +35 -0
  94. data/views/users.erb +69 -0
  95. metadata +256 -0
@@ -0,0 +1,156 @@
1
+ require 'puppetfactory'
2
+ require 'hocon'
3
+ require 'hocon/parser/config_document_factory'
4
+ require 'hocon/config_value_factory'
5
+
6
+ class Puppetfactory::Plugins::CodeManager < Puppetfactory::Plugins
7
+
8
+ def initialize(options)
9
+ super(options)
10
+
11
+ @puppet = options[:puppet]
12
+ @gitserver = options[:gitserver]
13
+ @repomodel = options[:repomodel]
14
+ @controlrepo = options[:controlrepo]
15
+ @environments = options[:environments]
16
+ @sources = '/etc/puppetlabs/puppet/hieradata/sources.yaml' # we can hardcode these assumptions
17
+ @meep = '/etc/puppetlabs/enterprise/conf.d/common.conf' # because CM is PE only.
18
+ @pattern = "#{@gitserver}/%s/#{@controlrepo}"
19
+
20
+ # the rest of this method is for the big boys only
21
+ return unless Process.euid == 0
22
+
23
+ # in case this is the first run and these doesn't exist yet
24
+ unless File.exist? @sources
25
+ FileUtils.mkdir_p File.dirname @sources
26
+ File.open(@sources, 'w') { |f| f.write( { 'puppet_enterprise::master::code_manager::sources' => {} }.to_yaml) }
27
+ end
28
+ File.open(@meep, 'w') { |f| f.write('') } unless File.exist? @meep
29
+
30
+ if options[:codedir]
31
+ # ensure sane file permissions
32
+ FileUtils.chown_R('pe-puppet', 'pe-puppet', options[:codedir])
33
+ FileUtils.chmod(0755, options[:codedir])
34
+ end
35
+ end
36
+
37
+ def create(username, password)
38
+ begin
39
+ environment = "#{@environments}/#{Puppetfactory::Helpers.environment_name(username)}"
40
+ FileUtils.mkdir_p environment
41
+ FileUtils.chown_R(username, 'pe-puppet', environment)
42
+ FileUtils.chmod(0750, environment)
43
+
44
+ File.open(@sources) do |file|
45
+ # make sure we don't have any concurrency issues
46
+ file.flock(File::LOCK_EX)
47
+
48
+ # We need to duplicate the sources list in the MEEP config for recovery options
49
+ # I'd like to add it to code-manager.conf too and avoid the delay of running
50
+ # puppet, but that's a race condition that we cannot accept.
51
+ File.open(@meep) do |anotherfile|
52
+ anotherfile.flock(File::LOCK_EX)
53
+
54
+ source = {
55
+ 'remote' => sprintf(@pattern, username),
56
+ 'prefix' => (@repomodel == :peruser),
57
+ }
58
+
59
+ sources = YAML.load_file(@sources)
60
+ meep = Hocon::Parser::ConfigDocumentFactory.parse_file(@meep)
61
+
62
+ sources['puppet_enterprise::master::code_manager::sources'][username] = source
63
+ meep = meep.set_config_value(
64
+ "\"puppet_enterprise::master::code_manager::sources\".#{username}",
65
+ Hocon::ConfigValueFactory.from_any_ref(source)
66
+ )
67
+
68
+ # Ruby 1.8.7, why don't you just go away now
69
+ File.open(@sources, 'w') { |f| f.write(sources.to_yaml) }
70
+ File.open(@meep, 'w') { |f| f.write(meep.render) }
71
+ $logger.info "Created Code Manager source for #{username}"
72
+ end
73
+ end
74
+ rescue => e
75
+ $logger.error "Cannot create Code Manager source for #{username}"
76
+ $logger.error e.backtrace
77
+ return false
78
+ end
79
+
80
+ true
81
+ end
82
+
83
+ def delete(username)
84
+ begin
85
+ environment = "#{@environments}/#{Puppetfactory::Helpers.environment_name(username)}"
86
+ FileUtils.rm_rf environment
87
+
88
+ # also delete any prefixed environments. Is this even a good idea?
89
+ FileUtils.rm_rf "#{@environments}/#{username}_*" if @repomodel == :peruser
90
+
91
+ File.open(@sources) do |file|
92
+ # make sure we don't have any concurrency issues
93
+ file.flock(File::LOCK_EX)
94
+
95
+ # We need to duplicate the sources list in the MEEP config for recovery options
96
+ # I'd like to add it to code-manager.conf too and avoid the delay of running
97
+ # puppet, but that's a race condition that we cannot accept.
98
+ File.open(@meep) do |anotherfile|
99
+ anotherfile.flock(File::LOCK_EX)
100
+
101
+ source = {
102
+ 'remote' => sprintf(@pattern, username),
103
+ 'prefix' => (@repomodel == :peruser),
104
+ }
105
+
106
+ sources = YAML.load_file(@sources)
107
+ sources['puppet_enterprise::master::code_manager::sources'].delete username rescue nil
108
+
109
+ meep = Hocon::Parser::ConfigDocumentFactory.parse_file(@meep)
110
+ meep = meep.remove_value("\"puppet_enterprise::master::code_manager::sources\".#{username}")
111
+
112
+ # Ruby 1.8.7, why don't you just go away now
113
+ File.open(@sources, 'w') { |f| f.write(sources.to_yaml) }
114
+ File.open(@meep, 'w') { |f| f.write(meep.render) }
115
+ $logger.info "Removed Code Manager source for #{username}"
116
+ end
117
+ end
118
+ rescue => e
119
+ $logger.error "Cannot remove Code Manager source for #{username}"
120
+ $logger.error e.backtrace
121
+ return false
122
+ end
123
+
124
+ true
125
+ end
126
+
127
+ def deploy(username)
128
+ environment = Puppetfactory::Helpers.environment_name(username)
129
+
130
+ output, status = Open3.capture2e(@puppet, 'code', 'deploy', environment, '--wait')
131
+ unless status.success?
132
+ $logger.error "Failed to deploy environment #{environment} for #{username}"
133
+ $logger.error output
134
+ return false
135
+ end
136
+
137
+ $logger.info "Deployed environment #{environment} for #{username}"
138
+ true
139
+ end
140
+
141
+ def redeploy(username)
142
+ begin
143
+ if username == 'production'
144
+ raise "Can't redeploy production environment"
145
+ end
146
+ delete(username)
147
+ deploy(username)
148
+
149
+ rescue => e
150
+ raise "Error redeploying environment #{username}: #{e.message}"
151
+ end
152
+
153
+ true
154
+ end
155
+
156
+ end
@@ -0,0 +1,62 @@
1
+ require 'json'
2
+ require 'puppetfactory'
3
+
4
+ class Puppetfactory::Plugins::ConsoleUser < Puppetfactory::Plugins
5
+
6
+ def initialize(options)
7
+ super(options)
8
+
9
+ @puppet = options[:puppet]
10
+ @suffix = options[:usersuffix]
11
+ auth_info = options[:auth_info] || {}
12
+
13
+ @ca_certificate_path = auth_info[:ca_certificate_path] || "#{options[:confdir]}/ssl/ca/ca_crt.pem",
14
+ @certificate_path = auth_info[:certificate_path] || "#{options[:confdir]}/ssl/certs/#{options[:master]}.pem",
15
+ @private_key_path = auth_info[:private_key_path] || "#{options[:confdir]}/ssl/private_keys/#{options[:master]}.pem"
16
+ @classifier_url = options[:classifier] || "http://#{options[:master]}:4433/classifier-api"
17
+ end
18
+
19
+ def create(username, password)
20
+ output, status = Open3.capture2e(@puppet, 'resource', 'rbac_user', username,
21
+ 'ensure=present',
22
+ "display_name=#{username}",
23
+ 'roles=Operators',
24
+ "email=#{username}@#{@suffix}",
25
+ "password=#{password}")
26
+
27
+ unless status.success
28
+ $logger.error "Could not create PE Console user #{username}: #{output}"
29
+ return false
30
+ end
31
+
32
+ $logger.info "Console user #{username} created successfully"
33
+ true
34
+ end
35
+
36
+ def delete(username)
37
+ output, status = Open3.capture2e(@puppet, 'resource', 'rbac_user', username, 'ensure=absent')
38
+ unless status.success?
39
+ $logger.warn "Could not remove PE Console user #{username}: #{output}"
40
+ return false
41
+ end
42
+
43
+ $logger.info "Console user #{username} removed successfully"
44
+ true
45
+ end
46
+
47
+ def userinfo(username, extended = false)
48
+ return unless extended
49
+
50
+ output, status = Open3.capture2e(PUPPET, 'resource', 'rbac_user', username)
51
+ unless status.success?
52
+ $logger.error "Could not query Puppet user #{username}: #{output}"
53
+ return false
54
+ end
55
+
56
+ {
57
+ :username => username,
58
+ :console_user => output =~ /present/,
59
+ }
60
+ end
61
+
62
+ end
@@ -0,0 +1,128 @@
1
+ require 'puppetfactory'
2
+
3
+ class Puppetfactory::Plugins::Dashboard < Puppetfactory::Plugins
4
+ attr_accessor :current_test
5
+
6
+ def initialize(options)
7
+ super(options)
8
+ return unless options[:puppetfactory]
9
+
10
+ @server = options[:puppetfactory]
11
+ @path = options[:dashboard_path] || '/etc/puppetfactory/dashboard'
12
+ @interval = options[:dashboard_interval] || 5 * 60 # test interval in seconds
13
+
14
+ # TODO: finish a real mutex implementation and avoid the current (small) race condition
15
+ #set :semaphore, Mutex.new
16
+ @current_test = 'summary'
17
+ @test_running = false
18
+
19
+ start_testing()
20
+
21
+ @server.get '/dashboard' do
22
+ protected!
23
+
24
+ # we can't call methods directly, because this block will execute in the scope
25
+ # of the Puppetfactory server. Use the plugin system instead.
26
+ @current = plugin(:Dashboard, :current_test)
27
+ @available = plugin(:Dashboard, :available_tests)
28
+ @test_data = plugin(:Dashboard, :test_data)
29
+
30
+ return 'No testing data' unless @available and @test_data
31
+
32
+ erb :dashboard
33
+ end
34
+
35
+ @server.get '/dashboard/details/:user' do |user|
36
+ plugin(:Dashboard, :user_test_html, user)
37
+ end
38
+
39
+ @server.get '/dashboard/details/:user/:result' do |user, result|
40
+ plugin(:Dashboard, :user_test_html, user, result)
41
+ end
42
+
43
+ @server.get '/dashboard/update' do
44
+ $logger.info "Triggering dashboard update."
45
+
46
+ if plugin(:Dashboard, :update_results)
47
+ {'status' => 'success'}.to_json
48
+ else
49
+ {'status' => 'fail', 'message' => 'Already running'}.to_json
50
+ end
51
+ end
52
+
53
+ @server.get '/dashboard/set/:current' do |current|
54
+ $logger.info "Setting current test to #{current}."
55
+
56
+ plugin(:Dashboard, :current_test=, current)
57
+
58
+ {'status' => 'success'}.to_json
59
+ end
60
+
61
+ end
62
+
63
+ def tabs(privileged = false)
64
+ return unless privileged
65
+
66
+ { 'dashboard' => 'Testing Dashboard' }
67
+ end
68
+
69
+ def update_results()
70
+ return false if @test_running
71
+ @test_running = true
72
+
73
+ Dir.chdir(@path) do
74
+ case @current_test
75
+ when 'all', 'summary'
76
+ system('rake', 'generate')
77
+ else
78
+ system('rake', 'generate', "current_test=#{@current_test}")
79
+ end
80
+ end
81
+
82
+ @test_running = false
83
+ true
84
+ end
85
+
86
+ def available_tests()
87
+ Dir.chdir(@path) { `rake list`.split } rescue []
88
+ end
89
+
90
+ def test_data()
91
+ JSON.parse(File.read("#{@path}/output/summary.json")) rescue {}
92
+ end
93
+
94
+ def user_test_html(user, result = @current_test)
95
+ begin
96
+ if result == 'summary'
97
+ File.read("#{@path}/output/html/#{user}.html")
98
+ else
99
+ File.read("#{@path}/output/html/#{result}/#{user}.html")
100
+ end
101
+ rescue Errno::ENOENT
102
+ 'No results found'
103
+ end
104
+ end
105
+
106
+ # class method so the template can call it
107
+ def self.test_completion(data)
108
+ total = data['example_count'] rescue 0
109
+ failed = data['failure_count'] rescue 0
110
+ passed = total - failed
111
+ percent = passed.to_f / total * 100.0 rescue 0
112
+
113
+ [total, passed, percent]
114
+ end
115
+
116
+ private
117
+ def start_testing()
118
+ Thread.new do
119
+ loop do
120
+ $logger.info "Updating dashboard after #{@interval} seconds."
121
+ update_results()
122
+ sleep(@interval)
123
+ end
124
+ end
125
+ end
126
+
127
+
128
+ end
@@ -0,0 +1,193 @@
1
+ require 'erb'
2
+ require 'time'
3
+ require 'docker'
4
+ require 'etc'
5
+ require 'json'
6
+ require 'puppetfactory'
7
+
8
+ class Puppetfactory::Plugins::Docker < Puppetfactory::Plugins
9
+
10
+ def initialize(options)
11
+ super(options)
12
+
13
+ @weight = 5
14
+
15
+ @confdir = options[:confdir]
16
+ @environments = options[:environments]
17
+ @puppetcode = options[:puppetcode]
18
+ @master = options[:master]
19
+ @modulepath = options[:modulepath]
20
+ @templatedir = options[:templatedir]
21
+ @container = options[:container_name] || 'centosagent'
22
+ @group = options[:docker_group] || 'docker'
23
+ @docker_ip = options[:docker_ip] || `facter ipaddress_docker0`.strip
24
+ @privileged = options[:privileged] || true
25
+ end
26
+
27
+ def create(username, password)
28
+ begin
29
+ environment = "#{@environments}/#{Puppetfactory::Helpers.environment_name(username)}"
30
+
31
+ binds = [
32
+ "/var/yum:/var/yum",
33
+ "/home/#{username}/puppet:#{@confdir}",
34
+ "/sys/fs/cgroup:/sys/fs/cgroup:ro"
35
+ ]
36
+
37
+ case @modulepath
38
+ when :readonly
39
+ binds.push("#{environment}:#{@puppetcode}:ro")
40
+ when :readwrite
41
+ binds.push("#{environment}:#{@puppetcode}")
42
+ when :none
43
+ #pass
44
+ else
45
+ raise "Uknown modulepath setting (#{@modulepath})"
46
+ end
47
+
48
+ container = ::Docker::Container.create(
49
+ "Cmd" => [
50
+ "/usr/lib/systemd/systemd"
51
+ ],
52
+ "Tty" => true,
53
+ "Domainname" => "puppetlabs.vm",
54
+ "Env" => [
55
+ "RUNLEVEL=3",
56
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
57
+ "HOME=/root/",
58
+ "TERM=xterm"
59
+ ],
60
+ "ExposedPorts" => {
61
+ "80/tcp" => {
62
+ }
63
+ },
64
+ "Hostname" => "#{username}",
65
+ "Image" => "#{@container}",
66
+ "HostConfig" => {
67
+ "Privileged" => @privileged,
68
+ "Binds" => binds,
69
+ "ExtraHosts" => [
70
+ "#{@master} puppet:#{@docker_ip}"
71
+ ],
72
+ "PortBindings" => {
73
+ "80/tcp" => [
74
+ {
75
+ "HostPort" => "#{user_port(username)}"
76
+ }
77
+ ]
78
+ },
79
+ },
80
+ "Name" => "#{username}"
81
+ )
82
+
83
+ container.rename(username) # Set container name so we can identify it
84
+ init_scripts(username) # Create init scripts so container restarts on boot
85
+ container.start
86
+
87
+ rescue => e
88
+ # fatal error, so we stop execution here
89
+ raise "Error creating container #{username}: #{e.message}"
90
+ end
91
+
92
+ $logger.info "Container #{username} created"
93
+ true
94
+ end
95
+
96
+ def delete(username)
97
+ begin
98
+ remove_init_scripts(username)
99
+
100
+ container = ::Docker::Container.get(username)
101
+ output = container.delete(:force => true)
102
+ rescue => e
103
+ $logger.warn "Error removing container #{username}: #{e.message}"
104
+ return false
105
+ end
106
+
107
+ $logger.info "Container #{username} removed"
108
+ true
109
+ end
110
+
111
+ def repair(username)
112
+ begin
113
+ container = ::Docker::Container.get(username)
114
+ container.delete(:force => true)
115
+
116
+ create(username, nil)
117
+ rescue => e
118
+ raise "Error reparing container #{username}: #{e.message}"
119
+ end
120
+
121
+ $logger.info "Container #{username} repaired"
122
+ true
123
+ end
124
+
125
+ def userinfo(username, extended = false)
126
+ user = {
127
+ :username => username,
128
+ :port => user_port(username),
129
+ :url => sandbox_url(username),
130
+ }
131
+
132
+ if extended
133
+ user_container = ::Docker::Container.get(username).json rescue {}
134
+ user[:container_status] = massage_container_state(user_container['State'])
135
+ end
136
+
137
+ user
138
+ end
139
+
140
+ def login
141
+ require 'etc'
142
+ username = Etc.getpwuid(Process.euid).name
143
+ exec("docker exec -it #{username} su -")
144
+ end
145
+
146
+ private
147
+ def sandbox_url(username)
148
+ "/port/#{user_port(username)}"
149
+ end
150
+
151
+ # TODO: We need a better way of doing this, since we're not guaranteed to always have system users.
152
+ # See plugins/shell_user.rb for the other side of this coupling.
153
+ def user_port(username)
154
+ Etc.getpwnam(username).uid + 3000
155
+ end
156
+
157
+ def massage_container_state(state)
158
+ return {'Description' => 'No container.'} if state.nil?
159
+
160
+ if state['OOMKilled']
161
+ state['Description'] = 'Halted because host machine is out of memory.'
162
+ elsif state['Restarting']
163
+ state['Description'] = 'Container is restarting.'
164
+ elsif state['Paused']
165
+ state['Description'] = 'Container is paused.'
166
+ elsif state['Running']
167
+ state['Description'] = "Running since #{Time.parse(state['StartedAt']).strftime("%b %d at %I:%M%p")}"
168
+ else
169
+ state['Description'] = 'Halted.'
170
+ end
171
+ state
172
+ end
173
+
174
+ def init_scripts(username)
175
+ service_file = "/etc/systemd/system/docker-#{username}.service"
176
+ File.open(service_file,"w") do |f|
177
+ f.write ERB.new(File.read("#{@templatedir}/init_scripts.erb")).result(binding)
178
+ end
179
+ File.chmod(0644, service_file)
180
+ system('chkconfig', "docker-#{username}", 'on')
181
+
182
+ $logger.info "Init scripts created and enabled for container #{username}"
183
+ end
184
+
185
+ def remove_init_scripts(username)
186
+ service_file = "/etc/systemd/system/docker-#{username}.service"
187
+ system('chkconfig', "docker-#{username}", 'off')
188
+ FileUtils.rm(service_file) if File.exist? service_file
189
+
190
+ $logger.info "Init scripts for container #{username} removed"
191
+ end
192
+
193
+ end