nuri 0.5.3 → 0.5.4
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.
- 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
|