nuri 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -1
- data/VERSION +1 -1
- data/bin/nuri +60 -14
- data/bin/nuri-install-module +17 -9
- data/examples/mockcloud/apache2.sfp +14 -0
- data/examples/mockcloud/ping.rb +38 -0
- data/examples/openstack/openstack-hadoop1-cluster.sfp +37 -0
- data/examples/openstack/openstack-hadoop2-cluster.sfp +39 -0
- data/examples/v2/apache.sfp +30 -0
- data/examples/v2/aptpackage.sfp +6 -0
- data/examples/v2/mock1.sfp +12 -0
- data/examples/v2/package.sfp +22 -0
- data/examples/v2/service.sfp +94 -0
- data/examples/v2/tarpackage.sfp +5 -0
- data/lib/nuri.rb +14 -10
- data/lib/nuri/choreographer.rb +3 -3
- data/lib/nuri/helper.rb +20 -10
- data/lib/nuri/master.rb +82 -54
- data/lib/nuri/orchestrator.rb +1 -1
- data/modules/.gitignore +0 -4
- data/modules/README.md +11 -0
- data/modules/apache/apache.sfp +2 -1
- data/modules/file/file.rb +49 -19
- data/modules/hadoop1/hadoop1.rb +18 -11
- data/modules/hadoop2/hadoop2.rb +11 -11
- data/modules/hadoop2/hadoop2.sfp +7 -6
- data/modules/hadoop2/yarn-site.xml +5 -0
- data/modules/machine/machine.rb +24 -14
- data/modules/openstack/README.md +24 -0
- data/modules/openstack/config.yml +5 -0
- data/modules/openstack/example.sfp +9 -0
- data/modules/openstack/openstack.rb +329 -0
- data/modules/openstack/openstack.sfp +24 -0
- data/modules/os/os.rb +1 -1
- data/modules/package2/apt-repo-list.sh +15 -0
- data/modules/package2/package2.rb +213 -43
- data/modules/package2/package2.sfp +3 -2
- data/modules/pyfile/README.md +4 -0
- data/modules/vm/vm.rb +3 -1
- data/modules/vm/vm.sfp +4 -3
- metadata +20 -3
- data/modules/hpcloud/test.sfp +0 -5
@@ -0,0 +1,329 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'thread'
|
3
|
+
require 'json'
|
4
|
+
require 'fog'
|
5
|
+
require 'yaml'
|
6
|
+
require 'net/ssh'
|
7
|
+
|
8
|
+
##############################
|
9
|
+
#
|
10
|
+
# Order of config file for credentials:
|
11
|
+
# 1) <HOME_DIRECTORY>/.hpcloud
|
12
|
+
# 2) <MODULE_DIRECTORY>/config.yml
|
13
|
+
#
|
14
|
+
#
|
15
|
+
# Order of SSH key file
|
16
|
+
# 1) <HOME_DIRECTORY>/.ssh/<KEY_PAIR_NAME>.pem
|
17
|
+
# 2) <HOME_DIRECTORY>/.ssh/<KEY_PAIR_NAME>
|
18
|
+
# 3) <MODULE_DIRECTORY>/<KEY_PAIR_NAME>.pem
|
19
|
+
# 4) <MODULE_DIRECTORY>/<KEY_PAIR_NAME>
|
20
|
+
# 5) <MODULE_DIRECTORY>/hpcloud.pem
|
21
|
+
#
|
22
|
+
##############################
|
23
|
+
|
24
|
+
class Sfp::Module::OpenStack
|
25
|
+
include Sfp::Resource
|
26
|
+
|
27
|
+
### Sleep time in waiting a task to be finished - default: 5s
|
28
|
+
SleepTime = 5
|
29
|
+
|
30
|
+
### Number of tries in waiting a task to be finished - default: 120 (10 minutes)
|
31
|
+
Tries = 600 / SleepTime
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@conn = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_state
|
38
|
+
to_model
|
39
|
+
|
40
|
+
@state['running'] = running?
|
41
|
+
@state['vms'] = get_vms
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
##############################
|
46
|
+
#
|
47
|
+
# Action methods (see hpcloud.sfp and cloud.sfp)
|
48
|
+
#
|
49
|
+
##############################
|
50
|
+
|
51
|
+
def create_vm(params={})
|
52
|
+
return false if not self.running?
|
53
|
+
|
54
|
+
### determine VM's name
|
55
|
+
name = params['vm'].sub(/^\$\./, '')
|
56
|
+
|
57
|
+
log.info "Creating VM #{name} [WAIT]"
|
58
|
+
|
59
|
+
### check if VM is already exist
|
60
|
+
if get_vms.has_key?(name)
|
61
|
+
log.info "VM #{name} is already exist - Creating VM #{name} [OK]"
|
62
|
+
return true
|
63
|
+
end
|
64
|
+
|
65
|
+
### get VM model from cache
|
66
|
+
vm_model = resolve_model(params['vm'])
|
67
|
+
|
68
|
+
### determine VM parameters
|
69
|
+
flavor = (vm_model['flavor'].to_s.length > 0 ? vm_model['flavor'].to_s : @model['vm_flavor'])
|
70
|
+
image = (vm_model['image'].to_s.length > 0 ? vm_model['image'].to_s : @model['vm_image'])
|
71
|
+
security_group = (vm_model['security_group'].to_s.length > 0 ? vm_model['security_group'].to_s : @model['vm_security_group'])
|
72
|
+
ssh_key_name = (vm_model['ssh_key_name'].to_s.length > 0 ? vm_model['ssh_key_name'].to_s : @model['vm_ssh_key_name'])
|
73
|
+
ssh_key_file = self.ssh_key_file(ssh_key_name)
|
74
|
+
ssh_user = (vm_model['ssh_user'].to_s.length > 0 ? vm_model['ssh_user'].to_s : @model['vm_ssh_user'].to_s)
|
75
|
+
|
76
|
+
### set network
|
77
|
+
networks = vm_model['networks'].keys.select! { |k| k[0] != '_' }
|
78
|
+
networks = Array(@model['vm_network']) if networks.length <= 0 and @model['vm_network'].strip.length > 0
|
79
|
+
nets = get_networks
|
80
|
+
networks.map! { |net| {'net_id' => nets[net]['id']} }
|
81
|
+
|
82
|
+
### check SSH key file
|
83
|
+
if ssh_key_file.nil?
|
84
|
+
log.info "SSH key file '#{ssh_key_file}' is not available! #{ssh_key_name} - Creating VM #{name} [Failed]"
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
log.info "#{name}:VM - SSH user: #{ssh_user}, SSH key file: #{ssh_key_file}"
|
88
|
+
|
89
|
+
spec = {
|
90
|
+
:name => name,
|
91
|
+
:flavor_ref => flavor,
|
92
|
+
:image_ref => image,
|
93
|
+
:key_name => ssh_key_name,
|
94
|
+
:security_groups => [security_group],
|
95
|
+
:metadata => {'name' => name},
|
96
|
+
}
|
97
|
+
spec['nics'] = networks if networks.length > 0
|
98
|
+
|
99
|
+
log.info "#{name}:VM - #{spec.inspect}"
|
100
|
+
|
101
|
+
### if not exist, then create the VM
|
102
|
+
created = false
|
103
|
+
begin
|
104
|
+
### submit create VM request
|
105
|
+
vm = @conn.servers.create(spec)
|
106
|
+
log.info "#{name}:VM - spec has been submitted"
|
107
|
+
|
108
|
+
### set SSH config
|
109
|
+
vm.username = ssh_user # 'ubuntu'
|
110
|
+
vm.private_key_path = ssh_key_file
|
111
|
+
|
112
|
+
log.info "#{name}:VM - ready [Wait]"
|
113
|
+
### wait until SSH is enabled
|
114
|
+
vm.wait_for { ready? }
|
115
|
+
log.info "#{name}:VM - ready [OK]"
|
116
|
+
|
117
|
+
log.info "#{name}:VM - sshable [Wait]"
|
118
|
+
### wait until SSH is sshable
|
119
|
+
ip = nil
|
120
|
+
vm.wait_for {
|
121
|
+
#vm.sshable? ### this does not work (fog's bug?)
|
122
|
+
ip = vm.addresses['default'].first['addr'].to_s if
|
123
|
+
vm.addresses['default'].is_a?(Array) and vm.addresses['default'].length > 0
|
124
|
+
if ip.length > 0
|
125
|
+
port = 22
|
126
|
+
begin
|
127
|
+
Timeout::timeout(1) do
|
128
|
+
begin
|
129
|
+
s = TCPSocket.new(ip, port)
|
130
|
+
s.close
|
131
|
+
true
|
132
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
133
|
+
false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
rescue Timeout::Error
|
137
|
+
false
|
138
|
+
end
|
139
|
+
else
|
140
|
+
false
|
141
|
+
end
|
142
|
+
}
|
143
|
+
log.info "#{name}:VM - sshable, ip: #{ip} [OK]"
|
144
|
+
|
145
|
+
### install sfpagent
|
146
|
+
created = install_agent(vm, name, ssh_key_file, ssh_user, ip)
|
147
|
+
|
148
|
+
rescue Exception => exp
|
149
|
+
log.info "#{exp}\n#{exp.backtrace.join("\n")}"
|
150
|
+
end
|
151
|
+
|
152
|
+
if not created
|
153
|
+
log.error "Creating VM #{name} [Failed]"
|
154
|
+
|
155
|
+
### delete if any error occured
|
156
|
+
delete_vm(params)
|
157
|
+
else
|
158
|
+
log.info "Creating VM #{name} [OK]"
|
159
|
+
end
|
160
|
+
|
161
|
+
created
|
162
|
+
end
|
163
|
+
|
164
|
+
def delete_vm(params={})
|
165
|
+
return false if not self.running?
|
166
|
+
|
167
|
+
### determine VM's name
|
168
|
+
name = params['vm'].sub(/^\$\./, '')
|
169
|
+
|
170
|
+
### check if VM is not exist
|
171
|
+
return true if !get_vms.has_key?(name)
|
172
|
+
|
173
|
+
### delete if VM with given name exists
|
174
|
+
@conn.servers.each { |s|
|
175
|
+
if s.name == name
|
176
|
+
@conn.delete_server(s.id)
|
177
|
+
break
|
178
|
+
end
|
179
|
+
}
|
180
|
+
|
181
|
+
### wait until the VM is completely deleted
|
182
|
+
tries = Tries
|
183
|
+
deleted = false
|
184
|
+
while not deleted and tries > 0
|
185
|
+
begin
|
186
|
+
deleted = !get_vms.has_key?(name)
|
187
|
+
break if deleted
|
188
|
+
rescue
|
189
|
+
end
|
190
|
+
log.info "VM:#{name} has been deleted."
|
191
|
+
tries -= 1
|
192
|
+
sleep SleepTime
|
193
|
+
end
|
194
|
+
|
195
|
+
deleted
|
196
|
+
end
|
197
|
+
|
198
|
+
def is_port_open?(ip, port)
|
199
|
+
begin
|
200
|
+
Timeout::timeout(1) do
|
201
|
+
begin
|
202
|
+
s = TCPSocket.new(ip, port)
|
203
|
+
s.close
|
204
|
+
true
|
205
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
206
|
+
false
|
207
|
+
end
|
208
|
+
end
|
209
|
+
rescue Timeout::Error
|
210
|
+
false
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
##############################
|
215
|
+
#
|
216
|
+
# Helper methods
|
217
|
+
#
|
218
|
+
##############################
|
219
|
+
|
220
|
+
protected
|
221
|
+
def config_file
|
222
|
+
return Dir.home + '/.openstack' if ::File.exist?(Dir.home + '/.openstack')
|
223
|
+
::File.dirname(__FILE__) + '/config.yml'
|
224
|
+
end
|
225
|
+
|
226
|
+
def read_config
|
227
|
+
return {} if not ::File.exist?(config_file)
|
228
|
+
return YAML.load_file(config_file)
|
229
|
+
end
|
230
|
+
|
231
|
+
def ssh_key_file(key_name)
|
232
|
+
file = Dir.home + '/.ssh/' + key_name + '.pem'
|
233
|
+
return file if ::File.exist?(file)
|
234
|
+
|
235
|
+
file = Dir.home + '/.ssh/' + key_name
|
236
|
+
return file if ::File.exist?(file)
|
237
|
+
|
238
|
+
file = File.dirname(__FILE__) + '/' + key_name + '.pem'
|
239
|
+
return file if ::File.exist?(file)
|
240
|
+
|
241
|
+
file = File.dirname(__FILE__) + '/' + key_name
|
242
|
+
return file if ::File.exist?(file)
|
243
|
+
|
244
|
+
file = File.dirname(__FILE__) + '/hpcloud.pem'
|
245
|
+
return file if ::File.exist?(file)
|
246
|
+
|
247
|
+
nil
|
248
|
+
end
|
249
|
+
|
250
|
+
def running?
|
251
|
+
return true if not @conn.nil?
|
252
|
+
begin
|
253
|
+
config = self.read_config
|
254
|
+
credential = {
|
255
|
+
:provider => :openstack,
|
256
|
+
:openstack_username => config['username'],
|
257
|
+
:openstack_api_key => config['password'],
|
258
|
+
:openstack_auth_url => @model['auth_uri'],
|
259
|
+
:openstack_tenant => config['tenant_id'],
|
260
|
+
}
|
261
|
+
@conn = Fog::Compute.new(credential)
|
262
|
+
@network = Fog::Network.new(credential)
|
263
|
+
|
264
|
+
rescue Exception => exp
|
265
|
+
log.error "#{exp}\n#{exp.backtrace.join("\n")}"
|
266
|
+
@conn = nil
|
267
|
+
end
|
268
|
+
return !!@conn
|
269
|
+
end
|
270
|
+
|
271
|
+
def get_vms
|
272
|
+
return {} if not running?
|
273
|
+
vms = {}
|
274
|
+
@conn.servers.each { |s|
|
275
|
+
spec = {
|
276
|
+
'running' => s.ready?,
|
277
|
+
'ip' => s.public_ip_address.to_s,
|
278
|
+
}
|
279
|
+
spec['ip'] = s.addresses['default'].first['addr'] if
|
280
|
+
spec['ip'].length <= 0 and s.addresses['default'].is_a?(Array) and s.addresses['default'].length > 0
|
281
|
+
vms[s.name] = spec
|
282
|
+
}
|
283
|
+
vms
|
284
|
+
end
|
285
|
+
|
286
|
+
def get_networks
|
287
|
+
nets = {}
|
288
|
+
@network.networks.each do |net|
|
289
|
+
nets[net.name] = {
|
290
|
+
'status' => net.status.downcase,
|
291
|
+
'id' => net.id
|
292
|
+
}
|
293
|
+
end
|
294
|
+
nets
|
295
|
+
end
|
296
|
+
|
297
|
+
def install_agent(vm, name, ssh_key_file=nil, ssh_user="ubuntu", ip=nil)
|
298
|
+
ip = vm.public_ip_address if ip.nil?
|
299
|
+
|
300
|
+
log.info "Installing agent on #{name}:VM, ip=#{ip} [Wait]"
|
301
|
+
|
302
|
+
begin
|
303
|
+
Net::SSH.start(ip, ssh_user, :keys => [ssh_key_file]) do |ssh|
|
304
|
+
if ssh.exec!('which sfpagent').strip.length <= 0
|
305
|
+
### install sfpagent
|
306
|
+
ssh.exec! 'apt-get update && ' +
|
307
|
+
'apt-get -y install sudo ruby1.9.1 ruby1.9.1-dev libz-dev libaugeas-ruby1.9.1 && ' +
|
308
|
+
'gem install sfp sfpagent net-ssh --no-ri --no-rdoc'
|
309
|
+
ssh.exec! 'sfpagent -t'
|
310
|
+
end
|
311
|
+
ssh.exec! 'sfpagent -s'
|
312
|
+
ssh.exec! "echo '#{path}' > /var/sfpagent/vm.in_cloud"
|
313
|
+
|
314
|
+
if ssh.exec!("hostname").strip != name
|
315
|
+
ssh.exec! "/bin/echo '#{name}' > /etc/hostname"
|
316
|
+
ssh.exec! "service hostname start; service hostname.sh start"
|
317
|
+
ssh.exec! "/bin/sed -i 's/#{name}.*/#{name}/g' /etc/hosts"
|
318
|
+
ssh.exec! "/bin/echo '#{ip} #{name}' >> /etc/hosts"
|
319
|
+
end
|
320
|
+
end
|
321
|
+
log.info "Installing agent on #{name}:VM, ip=#{ip} [OK]"
|
322
|
+
true
|
323
|
+
rescue Exception => exp
|
324
|
+
log.error "Installing agent on #{name}:VM, ip=#{ip} [Failed] - #{exp}\n#{exp.backtrace.join("\n")}"
|
325
|
+
false
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
include "../cloud/cloud.sfp"
|
2
|
+
|
3
|
+
schema OpenStack extends Cloud {
|
4
|
+
final description = "Openstack"
|
5
|
+
final auth_uri = "https://openstack.com/v2.0/tokens"
|
6
|
+
|
7
|
+
// default SSH username
|
8
|
+
final vm_ssh_user = "root"
|
9
|
+
|
10
|
+
// small instance
|
11
|
+
final vm_flavor = "2"
|
12
|
+
|
13
|
+
// default image
|
14
|
+
final vm_image = "67074"
|
15
|
+
|
16
|
+
// default key pair which will be used to SSH to VM
|
17
|
+
final vm_ssh_key_name = "default"
|
18
|
+
|
19
|
+
// default security group
|
20
|
+
final vm_security_group = "default"
|
21
|
+
|
22
|
+
// default network
|
23
|
+
final vm_network = "default"
|
24
|
+
}
|
data/modules/os/os.rb
CHANGED
@@ -21,7 +21,7 @@ class Sfp::Module::OS
|
|
21
21
|
@state["type"] = `uname -s`.strip
|
22
22
|
@state["version"] = `uname -r`.strip
|
23
23
|
@state["arch"] = `uname -p`.strip
|
24
|
-
@state["platform"] =
|
24
|
+
@state["platform"] = RUBY_PLATFORM
|
25
25
|
end
|
26
26
|
|
27
27
|
def apply(p={})
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#! /bin/sh
|
2
|
+
# Script to get all the PPA installed on a system
|
3
|
+
for APT in `find /etc/apt/ -name \*.list`; do
|
4
|
+
grep -Po "(?<=^deb\s).*?(?=#|$)" $APT | while read ENTRY ; do
|
5
|
+
HOST=`echo $ENTRY | cut -d/ -f3`
|
6
|
+
USER=`echo $ENTRY | cut -d/ -f4`
|
7
|
+
PPA=`echo $ENTRY | cut -d/ -f5`
|
8
|
+
#echo sudo apt-add-repository ppa:$USER/$PPA
|
9
|
+
if [ "ppa.launchpad.net" = "$HOST" ]; then
|
10
|
+
echo ppa:$USER/$PPA
|
11
|
+
else
|
12
|
+
echo ${ENTRY}
|
13
|
+
fi
|
14
|
+
done
|
15
|
+
done
|
@@ -4,66 +4,236 @@ class Sfp::Module::Package2
|
|
4
4
|
include Sfp::Resource
|
5
5
|
|
6
6
|
def update_state
|
7
|
-
|
7
|
+
provider = @model['provider'].strip
|
8
|
+
if provider != self.provider
|
9
|
+
case provider
|
10
|
+
when 'apt'
|
11
|
+
self.extend(AptPackage)
|
12
|
+
when 'tar'
|
13
|
+
self.extend(TarPackage)
|
14
|
+
else
|
15
|
+
self.extend(GenericPackage)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
get_state
|
20
|
+
end
|
8
21
|
|
9
|
-
|
10
|
-
|
22
|
+
def provider
|
23
|
+
nil
|
11
24
|
end
|
12
25
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
##############################
|
26
|
+
module GenericPackage
|
27
|
+
def provider
|
28
|
+
nil
|
29
|
+
end
|
18
30
|
|
19
|
-
|
31
|
+
def get_state
|
32
|
+
end
|
20
33
|
|
21
|
-
|
22
|
-
name = @model['name'].to_s.strip
|
23
|
-
if name.length > 0
|
24
|
-
data = `/usr/bin/dpkg-query -W #{name} 2>/dev/null`.strip.chop.split(' ')
|
25
|
-
(data[0].to_s == name)
|
26
|
-
else
|
34
|
+
def install(p={})
|
27
35
|
false
|
28
36
|
end
|
29
|
-
end
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
if name.length > 0
|
34
|
-
data = `/usr/bin/dpkg-query -W #{name} 2>/dev/null`.strip.chop.split(' ')
|
35
|
-
(data[0].to_s == name ? data[1] : "")
|
36
|
-
else
|
37
|
-
""
|
38
|
+
def uninstall(p={})
|
39
|
+
false
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
43
|
+
module TarPackage
|
44
|
+
def provider
|
45
|
+
'tar'
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_state
|
49
|
+
to_model
|
50
|
+
@state['installed'] = installed?
|
51
|
+
@state['version'] = version?
|
52
|
+
@state['home'] = (@state['installed'] ? @model['home'] : '')
|
53
|
+
end
|
54
|
+
|
55
|
+
def install(p={})
|
56
|
+
home = @model['home'].strip
|
57
|
+
return false if home.length <= 0
|
58
|
+
|
59
|
+
# create home directory if not exist
|
60
|
+
shell "rm -rf #{home} && mkdir -p #{home}" if not ::File.directory?(home)
|
61
|
+
if not ::File.directory?(home)
|
62
|
+
log.info "Target directory #{home} cannot be created."
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
|
66
|
+
file = url.split('/').last
|
67
|
+
dest = "#{home}/#{file}"
|
68
|
+
download(url, dest)
|
69
|
+
|
70
|
+
# if downloaded file is not exist, then return false
|
71
|
+
if not ::File.exist?(dest)
|
72
|
+
log.error "Failed to download file from #{url}"
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
|
76
|
+
# extract tar file, and then delete it
|
77
|
+
shell "cd #{home} && tar xvzf #{file} && rm -f #{file}"
|
78
|
+
|
79
|
+
basename = case ::File.extname(file)
|
80
|
+
when '.gz'
|
81
|
+
::File.basename(file, '.tar.gz')
|
82
|
+
when '.tgz'
|
83
|
+
::File.basename(file, '.tgz')
|
84
|
+
else
|
85
|
+
file
|
86
|
+
end
|
87
|
+
|
88
|
+
shell "bash -c 'cd #{home}/#{basename} && shopt -s dotglob && mv -f * .. && cd .. && rm -rf #{basename}'"
|
89
|
+
|
90
|
+
File.open("#{home}/#{signature}", 'w') { |f| f.write(Time.now.to_s) }
|
91
|
+
|
92
|
+
if not ::File.exist?(version_file)
|
93
|
+
File.open(version_file, 'w') { |f| f.write(@model['version']) }
|
94
|
+
end
|
95
|
+
|
96
|
+
installed?
|
97
|
+
end
|
98
|
+
|
99
|
+
def uninstall(p={})
|
100
|
+
shell "rm -rf #{@model['home']}" if ::File.exist?(@model['home'])
|
101
|
+
not installed?
|
102
|
+
end
|
103
|
+
|
104
|
+
def installed?
|
105
|
+
::File.file?("#{@model['home']}/#{signature}")
|
106
|
+
end
|
107
|
+
|
108
|
+
def version?
|
109
|
+
if ::File.file?(version_file)
|
110
|
+
File.read(version_file).strip
|
51
111
|
else
|
52
|
-
|
112
|
+
''
|
53
113
|
end
|
54
114
|
end
|
115
|
+
|
116
|
+
def version_file
|
117
|
+
"#{@model['home']}/VERSION"
|
118
|
+
end
|
119
|
+
|
120
|
+
def signature
|
121
|
+
".nuri.package"
|
122
|
+
end
|
123
|
+
|
124
|
+
def url
|
125
|
+
"#{@model['source']}/#{@model['name']}-#{@model['version']}.tar.gz"
|
126
|
+
end
|
55
127
|
end
|
56
128
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
129
|
+
module AptPackage
|
130
|
+
def provider
|
131
|
+
'apt'
|
132
|
+
end
|
133
|
+
|
134
|
+
def get_state
|
135
|
+
to_model
|
136
|
+
|
137
|
+
@state['installed'] = installed?
|
138
|
+
@state['version'] = version?
|
139
|
+
end
|
140
|
+
|
141
|
+
##############################
|
142
|
+
#
|
143
|
+
# Action methods (see Package2.sfp)
|
144
|
+
#
|
145
|
+
##############################
|
146
|
+
|
147
|
+
@@lock = Mutex.new
|
148
|
+
|
149
|
+
def installed?(p={})
|
150
|
+
name = (p.has_key?(:name) ? p[:name] : @model['name'].to_s.strip)
|
151
|
+
if name.length > 0
|
152
|
+
data = `/usr/bin/dpkg-query -W #{name} 2>/dev/null`.strip.chop.split(' ')
|
153
|
+
(data[0].to_s == name)
|
154
|
+
else
|
155
|
+
false
|
156
|
+
end
|
66
157
|
end
|
158
|
+
|
159
|
+
def version?(p={})
|
160
|
+
name = (p.has_key?(:name) ? p[:name] : @model['name'].to_s.strip)
|
161
|
+
if name.length > 0
|
162
|
+
data = `/usr/bin/dpkg-query -W #{name} 2>/dev/null`.strip.chop.split(' ')
|
163
|
+
(data[0].to_s == name ? data[1] : "")
|
164
|
+
else
|
165
|
+
""
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def install(p={})
|
170
|
+
return false if not repo_installed?
|
171
|
+
|
172
|
+
name = @model['name'].to_s.strip
|
173
|
+
if name.length <= 0
|
174
|
+
false
|
175
|
+
elsif installed?
|
176
|
+
true
|
177
|
+
else
|
178
|
+
shell "dpkg --configure -a; apt-get -y --purge autoremove"
|
179
|
+
if not shell "apt-get -y install #{name}"
|
180
|
+
shell "dpkg --configure -a; apt-get -y update && apt-get -y install #{name}"
|
181
|
+
end
|
182
|
+
installed?
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def uninstall(package)
|
187
|
+
name = @model['name'].to_s.strip
|
188
|
+
if name.length <= 0
|
189
|
+
false
|
190
|
+
elsif not installed?
|
191
|
+
true
|
192
|
+
else
|
193
|
+
shell "dpkg --configure -a; apt-get -y --purge autoremove"
|
194
|
+
shell "apt-get -y --purge remove #{name} && apt-get -y --purge autoremove && apt-get -y --purge autoremove"
|
195
|
+
not installed?
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
##############################
|
200
|
+
#
|
201
|
+
# Helper methods
|
202
|
+
#
|
203
|
+
##############################
|
204
|
+
|
205
|
+
def repo_installed?
|
206
|
+
if @model['provider'] == 'apt'
|
207
|
+
case @model['source'].strip
|
208
|
+
when 'default', ''
|
209
|
+
true
|
210
|
+
else
|
211
|
+
apt_repo_installed?
|
212
|
+
end
|
213
|
+
else
|
214
|
+
true
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def apt_repo_installed?
|
219
|
+
type, _ = @model['source'].split(':')
|
220
|
+
if type == 'ppa'
|
221
|
+
repos = `/bin/bash #{File.dirname(__FILE__)}/apt-repo-list.sh`.strip.split("\n")
|
222
|
+
if not repos.include?(@model['source'])
|
223
|
+
log.info "Missing APT repository: #{@model['source']}"
|
224
|
+
if not installed?({:name => 'python-software-properties'})
|
225
|
+
shell "apt-get install -y python-software-properties"
|
226
|
+
end
|
227
|
+
log.info "Adding APT repository: #{@model['source']}"
|
228
|
+
shell "add-apt-repository #{model['source']} && apt-get update"
|
229
|
+
else
|
230
|
+
false
|
231
|
+
end
|
232
|
+
else
|
233
|
+
false
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
67
237
|
end
|
68
238
|
|
69
239
|
=begin
|