fission 0.3.0 → 0.4.0.beta.1
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.
- data/.gitignore +1 -0
- data/CHANGELOG.md +3 -0
- data/README.md +1 -1
- data/lib/fission.rb +5 -6
- data/lib/fission/cli.rb +77 -7
- data/lib/fission/command.rb +43 -1
- data/lib/fission/command/clone.rb +19 -20
- data/lib/fission/command/delete.rb +29 -25
- data/lib/fission/command/snapshot_create.rb +11 -26
- data/lib/fission/command/snapshot_list.rb +13 -19
- data/lib/fission/command/snapshot_revert.rb +11 -26
- data/lib/fission/command/start.rb +11 -25
- data/lib/fission/command/status.rb +26 -10
- data/lib/fission/command/stop.rb +10 -21
- data/lib/fission/command/suspend.rb +21 -21
- data/lib/fission/command_helpers.rb +21 -0
- data/lib/fission/config.rb +35 -0
- data/lib/fission/fusion.rb +11 -3
- data/lib/fission/lease.rb +148 -0
- data/lib/fission/metadata.rb +55 -2
- data/lib/fission/response.rb +76 -0
- data/lib/fission/ui.rb +49 -0
- data/lib/fission/version.rb +1 -1
- data/lib/fission/vm.rb +653 -75
- data/spec/contexts/command.rb +12 -0
- data/spec/fission/cli_spec.rb +4 -11
- data/spec/fission/command/clone_spec.rb +45 -45
- data/spec/fission/command/delete_spec.rb +56 -43
- data/spec/fission/command/snapshot_create_spec.rb +29 -51
- data/spec/fission/command/snapshot_list_spec.rb +25 -26
- data/spec/fission/command/snapshot_revert_spec.rb +27 -53
- data/spec/fission/command/start_spec.rb +25 -69
- data/spec/fission/command/status_spec.rb +48 -13
- data/spec/fission/command/stop_spec.rb +25 -42
- data/spec/fission/command/suspend_spec.rb +54 -49
- data/spec/fission/command_helpers_spec.rb +30 -0
- data/spec/fission/command_spec.rb +19 -0
- data/spec/fission/config_spec.rb +24 -0
- data/spec/fission/fusion_spec.rb +6 -6
- data/spec/fission/lease_spec.rb +176 -0
- data/spec/fission/metadata_spec.rb +8 -8
- data/spec/fission/response_spec.rb +81 -0
- data/spec/fission/vm_spec.rb +869 -193
- data/spec/fission_spec.rb +0 -6
- data/spec/helpers/command_helpers.rb +12 -0
- data/spec/helpers/response_helpers.rb +21 -0
- data/spec/matchers/be_a_successful_response.rb +7 -0
- data/spec/matchers/be_an_unsuccessful_response.rb +10 -0
- data/spec/spec_helper.rb +7 -0
- metadata +24 -5
data/lib/fission/metadata.rb
CHANGED
@@ -3,8 +3,23 @@ module Fission
|
|
3
3
|
|
4
4
|
require 'cfpropertylist'
|
5
5
|
|
6
|
+
# Public: Gets/Sets the content (Hash).
|
6
7
|
attr_accessor :content
|
7
8
|
|
9
|
+
# Public: Deletes the Fusion metadata related to a VM. The VM should not be
|
10
|
+
# running when this method is called. It's highly recommended to call this
|
11
|
+
# method without the Fusion GUI application running. If the Fusion GUI is
|
12
|
+
# running this method should succeed, but it's been observed that Fusion
|
13
|
+
# will recreate the metadata which is deleted. This leads to 'missing' VMs
|
14
|
+
# in the Fusion GUI.
|
15
|
+
#
|
16
|
+
# vm_path - The absolute path to the directory of a VM.
|
17
|
+
#
|
18
|
+
# Examples
|
19
|
+
#
|
20
|
+
# Fission::Metadata.delete_vm_info '/vms/foo.vmwarevm'
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
8
23
|
def self.delete_vm_info(vm_path)
|
9
24
|
metadata = new
|
10
25
|
metadata.load
|
@@ -13,24 +28,62 @@ module Fission
|
|
13
28
|
metadata.save
|
14
29
|
end
|
15
30
|
|
31
|
+
# Public: Reads the configured metadata file and populates the content
|
32
|
+
# variable with native ruby types.
|
33
|
+
#
|
34
|
+
# Examples
|
35
|
+
#
|
36
|
+
# metadata.load
|
37
|
+
#
|
38
|
+
# Returns nothing.
|
16
39
|
def load
|
17
|
-
raw_data = CFPropertyList::List.new :file => Fission.config
|
40
|
+
raw_data = CFPropertyList::List.new :file => Fission.config['plist_file']
|
18
41
|
@content = CFPropertyList.native_types raw_data.value
|
19
42
|
end
|
20
43
|
|
44
|
+
# Public: Saves a new version of the metadata file with the data in the
|
45
|
+
# content variable.
|
46
|
+
#
|
47
|
+
# Examples
|
48
|
+
#
|
49
|
+
# metadata.save
|
50
|
+
#
|
51
|
+
# Returns nothing.
|
21
52
|
def save
|
22
53
|
new_content = CFPropertyList::List.new
|
23
54
|
new_content.value = CFPropertyList.guess @content
|
24
|
-
new_content.save Fission.config
|
55
|
+
new_content.save Fission.config['plist_file'],
|
25
56
|
CFPropertyList::List::FORMAT_BINARY
|
26
57
|
end
|
27
58
|
|
59
|
+
# Public: Deletes the VM information from the 'restart document path'
|
60
|
+
# metadata. The 'restart document path' dictates which GUI consoles to
|
61
|
+
# display when Fusion starts.
|
62
|
+
#
|
63
|
+
# vm_path - The absolute path to the directory of a VM.
|
64
|
+
#
|
65
|
+
# Examples
|
66
|
+
#
|
67
|
+
# metadata.delete_vm_restart_document 'vms/foo.vmwarevm'
|
68
|
+
#
|
69
|
+
# Returns nothing.
|
28
70
|
def delete_vm_restart_document(vm_path)
|
29
71
|
if @content.has_key?('PLRestartDocumentPaths')
|
30
72
|
@content['PLRestartDocumentPaths'].delete_if { |p| p == vm_path }
|
31
73
|
end
|
32
74
|
end
|
33
75
|
|
76
|
+
# Public: Deletes the VM information from the 'favorites list' metadata.
|
77
|
+
# The 'favorites list' dictates which VMs are displayed in the Fusion VM
|
78
|
+
# libarary.
|
79
|
+
#
|
80
|
+
# vm_path - The absolute path to the directory of a VM.
|
81
|
+
#
|
82
|
+
# Examples
|
83
|
+
#
|
84
|
+
# metadata.delete_favorite_entry '/vms/foo.vmwarevm'
|
85
|
+
#
|
86
|
+
# Returns nothing.
|
34
87
|
def delete_vm_favorite_entry(vm_path)
|
35
88
|
@content['VMFavoritesListDefaults2'].delete_if { |vm| vm['path'] == vm_path }
|
36
89
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Fission
|
2
|
+
class Response
|
3
|
+
|
4
|
+
# Public: Gets/Sets the code (Integer).
|
5
|
+
attr_accessor :code
|
6
|
+
|
7
|
+
# Public: Gets/Sets the message (String).
|
8
|
+
attr_accessor :message
|
9
|
+
|
10
|
+
# Public: Gets/Sets the data (can be any of type as needed).
|
11
|
+
attr_accessor :data
|
12
|
+
|
13
|
+
# Public: Initialize a Response object.
|
14
|
+
#
|
15
|
+
# args - Hash of arguments:
|
16
|
+
# :code - Integer which denotes the code of the Response. This is
|
17
|
+
# similar in concept to command line exit codes. The
|
18
|
+
# convention is that 0 denotes success and any other value
|
19
|
+
# is unsuccessful (default: 1).
|
20
|
+
# :message - String which denotes the message of the Response. The
|
21
|
+
# convention is that this should only be used when the
|
22
|
+
# Response is unsuccessful (default: '').
|
23
|
+
# :data - Any valid ruby object. This is used to convey any
|
24
|
+
# data that needs to be used by a caller. The convention
|
25
|
+
# is that this should only be used when the Response is
|
26
|
+
# successful (default nil).
|
27
|
+
#
|
28
|
+
# Examples
|
29
|
+
#
|
30
|
+
# Response.new :code => 0, :data => [1, 2, 3, 4]
|
31
|
+
#
|
32
|
+
# Response.new :code => 0, :data => true
|
33
|
+
#
|
34
|
+
# Response.new :code => 5, :message => 'Something went wrong'
|
35
|
+
#
|
36
|
+
# Returns a new Response instance.
|
37
|
+
def initialize(args={})
|
38
|
+
@code = args.fetch :code, 1
|
39
|
+
@message = args.fetch :message, ''
|
40
|
+
@data = args.fetch :data, nil
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: Helper method to determine if a response is successful or not.
|
44
|
+
#
|
45
|
+
# Examples
|
46
|
+
#
|
47
|
+
# response.successful?
|
48
|
+
# # => true
|
49
|
+
#
|
50
|
+
# response.successful?
|
51
|
+
# # => false
|
52
|
+
#
|
53
|
+
# Returns a Boolean.
|
54
|
+
# Returns true if the code is 0.
|
55
|
+
# Returns false if the code is any other value.
|
56
|
+
def successful?
|
57
|
+
@code == 0
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: Helper method to create a new Response object when running a
|
61
|
+
# command line tool.
|
62
|
+
#
|
63
|
+
# cmd_output - This should be the output of the command.
|
64
|
+
#
|
65
|
+
# Returns a Response.
|
66
|
+
# The Response's code attribute will be set to the value of '$?'. The
|
67
|
+
# Response's message attribute will be set to the provided command output
|
68
|
+
# if, and only if, the Response is unsuccessful.
|
69
|
+
def self.from_command(cmd_output)
|
70
|
+
response = new :code => $?.exitstatus
|
71
|
+
response.message = cmd_output unless response.successful?
|
72
|
+
response
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
data/lib/fission/ui.rb
CHANGED
@@ -1,19 +1,68 @@
|
|
1
1
|
module Fission
|
2
2
|
class UI
|
3
|
+
|
4
|
+
# Internal: Returns the stdout value.
|
3
5
|
attr_reader :stdout
|
4
6
|
|
7
|
+
# Internal: Initialize a UI object.
|
8
|
+
#
|
9
|
+
# stdout - The object to use for stdout (default: $stdout). This provides
|
10
|
+
# an easy way to capture/silence output if needed.
|
11
|
+
#
|
12
|
+
# Examples
|
13
|
+
#
|
14
|
+
# Fission::UI.new
|
15
|
+
#
|
16
|
+
# str_io = StringIO.new
|
17
|
+
# Fission::UI.new str_io
|
5
18
|
def initialize(stdout=$stdout)
|
6
19
|
@stdout = stdout
|
7
20
|
end
|
8
21
|
|
22
|
+
# Internal: Outputs the specified argument to the configured stdout object.
|
23
|
+
# The 'puts' method will be called on the stdout object.
|
24
|
+
#
|
25
|
+
# s - The String to output.
|
26
|
+
#
|
27
|
+
# Examples
|
28
|
+
#
|
29
|
+
# ui.output "foo bar\n"
|
30
|
+
#
|
31
|
+
# Returns nothing.
|
9
32
|
def output(s)
|
10
33
|
@stdout.puts s
|
11
34
|
end
|
12
35
|
|
36
|
+
# Internal: Outputs the specified arguments printf style. The 'printf'
|
37
|
+
# method will be called on the stdout object. Currently, this assuems there
|
38
|
+
# are two data items.
|
39
|
+
#
|
40
|
+
# string - The printf String.
|
41
|
+
# key - The String for the first data item.
|
42
|
+
# value - The String for the second data item.
|
43
|
+
#
|
44
|
+
# Examples
|
45
|
+
#
|
46
|
+
# ui.output_printf "%s %s\n", 'foo', bar
|
47
|
+
#
|
48
|
+
# Returns nothing.
|
13
49
|
def output_printf(string, key, value)
|
14
50
|
@stdout.send :printf, string, key, value
|
15
51
|
end
|
16
52
|
|
53
|
+
# Internal: Outputs the specified argument to the configured stdout object
|
54
|
+
# and exits with the specified exit code.
|
55
|
+
#
|
56
|
+
# s - The String to output.
|
57
|
+
# exit_code - The Integer exit code.
|
58
|
+
#
|
59
|
+
# Examples
|
60
|
+
#
|
61
|
+
# ui.output_and_exit 'something went wrong', 99
|
62
|
+
#
|
63
|
+
# ui.output_and_exit 'all done', 0
|
64
|
+
#
|
65
|
+
# Returns nothing.
|
17
66
|
def output_and_exit(s, exit_code)
|
18
67
|
output s
|
19
68
|
exit exit_code
|
data/lib/fission/version.rb
CHANGED
data/lib/fission/vm.rb
CHANGED
@@ -1,158 +1,654 @@
|
|
1
1
|
module Fission
|
2
2
|
class VM
|
3
|
+
|
4
|
+
# Public: Gets the name of the VM as a String.
|
3
5
|
attr_reader :name
|
4
6
|
|
5
7
|
def initialize(name)
|
6
8
|
@name = name
|
7
9
|
end
|
8
10
|
|
11
|
+
# Public: Creates a snapshot for a VM. The VM must be running in order
|
12
|
+
# to create a snapshot. Snapshot names must be unique.
|
13
|
+
#
|
14
|
+
# name - The desired name of the snapshot. The name must be unique.
|
15
|
+
#
|
16
|
+
# Examples
|
17
|
+
#
|
18
|
+
# @vm.create_snapshot('foo_snap_1')
|
19
|
+
#
|
20
|
+
# Returns a Response with the result.
|
21
|
+
# If successful, the Response's data attribute will be nil.
|
22
|
+
# If there is an error, an unsuccessful Response will be returned.
|
9
23
|
def create_snapshot(name)
|
10
|
-
|
11
|
-
|
24
|
+
unless exists?
|
25
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
26
|
+
end
|
12
27
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
28
|
+
running_response = running?
|
29
|
+
return running_response unless running_response.successful?
|
30
|
+
|
31
|
+
unless running_response.data
|
32
|
+
message = 'The VM must be running in order to take a snapshot.'
|
33
|
+
return Response.new :code => 1, :message => message
|
18
34
|
end
|
35
|
+
|
36
|
+
conf_file_response = conf_file
|
37
|
+
return conf_file_response unless conf_file_response.successful?
|
38
|
+
|
39
|
+
snapshots_response = snapshots
|
40
|
+
return snapshots_response unless snapshots_response.successful?
|
41
|
+
|
42
|
+
if snapshots_response.data.include? name
|
43
|
+
message = "There is already a snapshot named '#{name}'."
|
44
|
+
return Response.new :code => 1, :message => message
|
45
|
+
end
|
46
|
+
|
47
|
+
command = "#{vmrun_cmd} snapshot "
|
48
|
+
command << "#{conf_file_response.data} \"#{name}\" 2>&1"
|
49
|
+
|
50
|
+
Response.from_command(`#{command}`)
|
19
51
|
end
|
20
52
|
|
53
|
+
# Public: Reverts the VM to the specified snapshot. The snapshot to revert
|
54
|
+
# to must exist and the Fusion GUI must not be running.
|
55
|
+
#
|
56
|
+
# name - The snapshot name to revert to.
|
57
|
+
#
|
58
|
+
# Examples
|
59
|
+
#
|
60
|
+
# @vm.revert_to_snapshot('foo_snap_1')
|
61
|
+
#
|
62
|
+
# Returns a Response with the result.
|
63
|
+
# If successful, the Response's data attribute will be nil.
|
64
|
+
# If there is an error, an unsuccessful Response will be returned.
|
21
65
|
def revert_to_snapshot(name)
|
22
|
-
|
23
|
-
|
66
|
+
unless exists?
|
67
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
68
|
+
end
|
24
69
|
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
70
|
+
if Fusion.running?
|
71
|
+
message = 'It looks like the Fusion GUI is currently running. '
|
72
|
+
message << 'A VM cannot be reverted to a snapshot when the Fusion GUI is running. '
|
73
|
+
message << 'Exit the Fusion GUI and try again.'
|
74
|
+
return Response.new :code => 1, :message => message
|
30
75
|
end
|
76
|
+
|
77
|
+
conf_file_response = conf_file
|
78
|
+
return conf_file_response unless conf_file_response.successful?
|
79
|
+
|
80
|
+
snapshots_response = snapshots
|
81
|
+
return snapshots_response unless snapshots_response.successful?
|
82
|
+
|
83
|
+
unless snapshots_response.data.include? name
|
84
|
+
message = "Unable to find a snapshot named '#{name}'."
|
85
|
+
return Response.new :code => 1, :message => message
|
86
|
+
end
|
87
|
+
|
88
|
+
command = "#{vmrun_cmd} revertToSnapshot "
|
89
|
+
command << "#{conf_file_response.data} \"#{name}\" 2>&1"
|
90
|
+
|
91
|
+
Response.from_command(`#{command}`)
|
31
92
|
end
|
32
93
|
|
94
|
+
# Public: List the snapshots for a VM.
|
95
|
+
#
|
96
|
+
# Examples
|
97
|
+
#
|
98
|
+
# @vm.snapshots.data
|
99
|
+
# # => ['snap 1', 'snap 2']
|
100
|
+
#
|
101
|
+
# Returns a Response with the result.
|
102
|
+
# If successful, the Repsonse's data attribute will be an Array of the
|
103
|
+
# snapshot names (String).
|
104
|
+
# If there is an error, an unsuccessful Response will be returned.
|
33
105
|
def snapshots
|
34
|
-
|
106
|
+
unless exists?
|
107
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
108
|
+
end
|
109
|
+
|
110
|
+
conf_file_response = conf_file
|
111
|
+
return conf_file_response unless conf_file_response.successful?
|
112
|
+
|
113
|
+
command = "#{vmrun_cmd} listSnapshots "
|
114
|
+
command << "#{conf_file_response.data} 2>&1"
|
35
115
|
output = `#{command}`
|
36
116
|
|
37
|
-
|
117
|
+
response = Response.new :code => $?.exitstatus
|
118
|
+
|
119
|
+
if response.successful?
|
38
120
|
snaps = output.split("\n").select { |s| !s.include? 'Total snapshots:' }
|
39
|
-
snaps.map { |s| s.strip }
|
121
|
+
response.data = snaps.map { |s| s.strip }
|
40
122
|
else
|
41
|
-
|
42
|
-
Fission.ui.output_and_exit "The error was:\n#{output}", 1
|
123
|
+
response.message = output
|
43
124
|
end
|
125
|
+
|
126
|
+
response
|
44
127
|
end
|
45
128
|
|
46
|
-
|
47
|
-
|
129
|
+
# Public: Starts a VM. The VM must not be running in order to start it.
|
130
|
+
#
|
131
|
+
# options - Hash of options:
|
132
|
+
# :headless - Boolean which specifies to start the VM without a
|
133
|
+
# GUI console. The Fusion GUI must not be running in
|
134
|
+
# order to start the VM headless.
|
135
|
+
# (default: false)
|
136
|
+
#
|
137
|
+
# Examples
|
138
|
+
#
|
139
|
+
# @vm.start
|
140
|
+
#
|
141
|
+
# @vm.start :headless => true
|
142
|
+
#
|
143
|
+
# Returns a Response with the result.
|
144
|
+
# If successful, the Response's data attribute will be nil.
|
145
|
+
# If there is an error, an unsuccessful Response will be returned.
|
146
|
+
def start(options={})
|
147
|
+
unless exists?
|
148
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
149
|
+
end
|
48
150
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
151
|
+
running_response = running?
|
152
|
+
return running_response unless running_response.successful?
|
153
|
+
|
154
|
+
if running_response.data
|
155
|
+
return Response.new :code => 1, :message => 'VM is already running'
|
53
156
|
end
|
54
157
|
|
55
|
-
|
158
|
+
conf_file_response = conf_file
|
159
|
+
return conf_file_response unless conf_file_response.successful?
|
56
160
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
161
|
+
unless options[:headless].blank?
|
162
|
+
if Fusion.running?
|
163
|
+
message = 'It looks like the Fusion GUI is currently running. '
|
164
|
+
message << 'A VM cannot be started in headless mode when the Fusion GUI is running. '
|
165
|
+
message << 'Exit the Fusion GUI and try again.'
|
166
|
+
return Response.new :code => 1, :message => message
|
167
|
+
end
|
61
168
|
end
|
169
|
+
|
170
|
+
command = "#{vmrun_cmd} start "
|
171
|
+
command << "#{conf_file_response.data} "
|
172
|
+
|
173
|
+
command << (options[:headless].blank? ? 'gui ' : 'nogui ')
|
174
|
+
command << '2>&1'
|
175
|
+
|
176
|
+
Response.from_command(`#{command}`)
|
62
177
|
end
|
63
178
|
|
64
|
-
|
65
|
-
|
66
|
-
|
179
|
+
# Public: Stops a VM. The VM must be running in order to stop it.
|
180
|
+
#
|
181
|
+
# options - Hash of options:
|
182
|
+
# :hard - Boolean which specifies to power off the VM (instead of
|
183
|
+
# attempting to initiate a graceful shutdown). This is
|
184
|
+
# the equivalent of passing 'hard' to the vmrun stop
|
185
|
+
# command.
|
186
|
+
# (default: false)
|
187
|
+
#
|
188
|
+
# Examples
|
189
|
+
#
|
190
|
+
# @vm.stop
|
191
|
+
#
|
192
|
+
# @vm.stop :hard => true
|
193
|
+
#
|
194
|
+
# Returns a Response with the result.
|
195
|
+
# If successful, the Response's data attribute will be nil.
|
196
|
+
# If there is an error, an unsuccessful Response will be returned.
|
197
|
+
def stop(options={})
|
198
|
+
unless exists?
|
199
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
200
|
+
end
|
67
201
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
202
|
+
running_response = running?
|
203
|
+
return running_response unless running_response.successful?
|
204
|
+
|
205
|
+
unless running_response.data
|
206
|
+
return Response.new :code => 1, :message => 'VM is not running'
|
72
207
|
end
|
208
|
+
|
209
|
+
conf_file_response = conf_file
|
210
|
+
return conf_file_response unless conf_file_response.successful?
|
211
|
+
|
212
|
+
command = "#{vmrun_cmd} stop "
|
213
|
+
command << "#{conf_file_response.data} "
|
214
|
+
command << 'hard ' unless options[:hard].blank?
|
215
|
+
command << '2>&1'
|
216
|
+
|
217
|
+
Response.from_command(`#{command}`)
|
73
218
|
end
|
74
219
|
|
220
|
+
# Public: Suspends a VM. The VM must be running in order to suspend it.
|
221
|
+
#
|
222
|
+
# Examples
|
223
|
+
#
|
224
|
+
# @vm.suspend
|
225
|
+
#
|
226
|
+
# Returns a Response with the result.
|
227
|
+
# If successful, the Response's data attribute will be nil.
|
228
|
+
# If there is an error, an unsuccessful Response will be returned.
|
75
229
|
def suspend
|
76
|
-
|
77
|
-
|
230
|
+
unless exists?
|
231
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
232
|
+
end
|
233
|
+
|
234
|
+
running_response = running?
|
235
|
+
return running_response unless running_response.successful?
|
236
|
+
|
237
|
+
unless running_response.data
|
238
|
+
return Response.new :code => 1, :message => 'VM is not running'
|
239
|
+
end
|
240
|
+
|
241
|
+
conf_file_response = conf_file
|
242
|
+
return conf_file_response unless conf_file_response.successful?
|
243
|
+
|
244
|
+
command = "#{vmrun_cmd} suspend "
|
245
|
+
command << "#{conf_file_response.data} 2>&1"
|
246
|
+
|
247
|
+
Response.from_command(`#{command}`)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Public: Provides the MAC addresses for a VM.
|
251
|
+
#
|
252
|
+
# Examples:
|
253
|
+
#
|
254
|
+
# @vm.mac_addresses.data
|
255
|
+
# # => ['00:0c:29:1d:6a:64', '00:0c:29:1d:6a:75']
|
256
|
+
#
|
257
|
+
# Returns a Response with the result.
|
258
|
+
# If successful, the Response's data attribute will be an Array of the MAC
|
259
|
+
# addresses found. If no MAC addresses are found, the Response's data
|
260
|
+
# attribute will be an empty Array.
|
261
|
+
# If there is an error, an unsuccessful Response will be returned.
|
262
|
+
def mac_addresses
|
263
|
+
network_response = network_info
|
264
|
+
return network_response unless network_response.successful?
|
265
|
+
|
266
|
+
response = Response.new :code => 0
|
267
|
+
response.data = network_response.data.values.collect { |n| n['mac_address'] }
|
268
|
+
|
269
|
+
response
|
270
|
+
end
|
271
|
+
|
272
|
+
# Public: Network information for a VM. Includes interface name, associated
|
273
|
+
# MAC address, and IP address (if applicable).
|
274
|
+
#
|
275
|
+
# Examples:
|
276
|
+
#
|
277
|
+
# # if IP addresses are found in the Fusion DHCP lease file
|
278
|
+
# response = @vm.network_info.data
|
279
|
+
# # => { 'ethernet0' => { 'mac_address' => '00:0c:29:1d:6a:64',
|
280
|
+
# 'ip_address' => '127.0.0.1' },
|
281
|
+
# 'ethernet1' => { 'mac_address' => '00:0c:29:1d:6a:75',
|
282
|
+
# 'ip_address' => '127.0.0.2' } }
|
283
|
+
#
|
284
|
+
# # if IP addresses are not found in the Fusion DHCP lease file
|
285
|
+
# response = @vm.network_info.data
|
286
|
+
# # => { 'ethernet0' => { 'mac_address' => '00:0c:29:1d:6a:64',
|
287
|
+
# 'ip_address' => nil },
|
288
|
+
# 'ethernet1' => { 'mac_address' => '00:0c:29:1d:6a:75',
|
289
|
+
# 'ip_address' => nil } }
|
290
|
+
#
|
291
|
+
# Returns a Response with the result.
|
292
|
+
# If successful, the Response's data attribute will be a Hash with the
|
293
|
+
# interface identifiers as the keys and the associated MAC address. If an
|
294
|
+
# IP address was found in the Fusion DHCP lease file, then it will
|
295
|
+
# be included. If an IP address was not found, then the IP address value
|
296
|
+
# will be nil. If there are no network interfaces, the Response's data
|
297
|
+
# attribute will be an empty Hash.
|
298
|
+
# If there is an error, an unsuccessful Response will be returned.
|
299
|
+
def network_info
|
300
|
+
conf_file_response = conf_file
|
301
|
+
return conf_file_response unless conf_file_response.successful?
|
302
|
+
|
303
|
+
response = Response.new :code => 0, :data => {}
|
304
|
+
|
305
|
+
interface_pattern = /^ethernet\d+/
|
306
|
+
mac_pattern = /(\w\w[:-]\w\w[:-]\w\w[:-]\w\w[:-]\w\w[:-]\w\w)/
|
307
|
+
|
308
|
+
File.open conf_file_response.data, 'r' do |f|
|
309
|
+
f.grep(mac_pattern).each do |line|
|
310
|
+
int = line.scan(interface_pattern)[0]
|
311
|
+
mac = line.scan(mac_pattern)[0].first
|
312
|
+
response.data[int] = {}
|
313
|
+
response.data[int]['mac_address'] = mac
|
314
|
+
|
315
|
+
lease_response = Fission::Lease.find_by_mac_address mac
|
316
|
+
return lease_response unless lease_response.successful?
|
317
|
+
|
318
|
+
response.data[int]['ip_address'] = nil
|
319
|
+
|
320
|
+
if lease_response.data
|
321
|
+
response.data[int]['ip_address'] = lease_response.data.ip_address
|
322
|
+
end
|
78
323
|
|
79
|
-
|
80
|
-
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
response
|
328
|
+
end
|
329
|
+
|
330
|
+
# Public: Provides the state of the VM.
|
331
|
+
#
|
332
|
+
# Examples
|
333
|
+
#
|
334
|
+
# @vm.state.data
|
335
|
+
# # => 'running'
|
336
|
+
#
|
337
|
+
# @vm.state.data
|
338
|
+
# # => 'not running'
|
339
|
+
#
|
340
|
+
# @vm.state.data
|
341
|
+
# # => 'suspended'
|
342
|
+
#
|
343
|
+
# Returns a Response with the result.
|
344
|
+
# If the Response is successful, the Response's data attribute will
|
345
|
+
# be a String of the state. If the VM is currently powered on, the state
|
346
|
+
# will be 'running'. If the VM is deemed to be suspended, the state will be
|
347
|
+
# 'suspended'. If the VM is not running and not deemed to be suspended, the
|
348
|
+
# state will be 'not running'.
|
349
|
+
# If there is an error, an unsuccessful Response will be returned.
|
350
|
+
def state
|
351
|
+
running_response = running?
|
352
|
+
return running_response unless running_response.successful?
|
353
|
+
|
354
|
+
response = Response.new :code => 0, :data => 'not running'
|
355
|
+
|
356
|
+
if running_response.data
|
357
|
+
response.data = 'running'
|
81
358
|
else
|
82
|
-
|
359
|
+
suspended_response = suspended?
|
360
|
+
return suspended_response unless suspended_response.successful?
|
361
|
+
|
362
|
+
response.data = 'suspended' if suspended_response.data
|
363
|
+
end
|
364
|
+
|
365
|
+
response
|
366
|
+
end
|
367
|
+
|
368
|
+
# Public: Determines if the VM exists or not. This method looks for the
|
369
|
+
# VM's conf file ('.vmx') to determine if the VM exists or not.
|
370
|
+
#
|
371
|
+
# Examples
|
372
|
+
#
|
373
|
+
# @vm.exists?
|
374
|
+
# # => true
|
375
|
+
#
|
376
|
+
# Returns a Boolean.
|
377
|
+
def exists?
|
378
|
+
conf_file.successful?
|
379
|
+
end
|
380
|
+
|
381
|
+
# Public: Determines if a VM is suspended.
|
382
|
+
#
|
383
|
+
# Examples
|
384
|
+
#
|
385
|
+
# @vm.suspended?.data
|
386
|
+
# # => true
|
387
|
+
#
|
388
|
+
# Returns a Response with the result.
|
389
|
+
# If successful, the Response's data attribute will be a Boolean. If the VM
|
390
|
+
# is not running, then this method will look for a '.vmem' file in the VM's
|
391
|
+
# directory. If a '.vmem' file exists and it matches the name of the VM,
|
392
|
+
# then the VM is considered to be suspended. If the VM is running or if a
|
393
|
+
# matching '.vmem' file is not found, then the VM is not considered to be
|
394
|
+
# suspended.
|
395
|
+
# If there is an error, an unsuccessful Response will be returned.
|
396
|
+
def suspended?
|
397
|
+
running_response = running?
|
398
|
+
return running_response unless running_response.successful?
|
399
|
+
|
400
|
+
response = Response.new :code => 0, :data => false
|
401
|
+
response.data = suspend_file_exists? unless running_response.data
|
402
|
+
|
403
|
+
response
|
404
|
+
end
|
405
|
+
|
406
|
+
# Public: Determines if a VM has a suspend file ('.vmem') in it's directory.
|
407
|
+
# This only looks for a suspend file which matches the name of the VM.
|
408
|
+
#
|
409
|
+
# Examples
|
410
|
+
#
|
411
|
+
# @vm.suspend_file_exists?
|
412
|
+
# # => true
|
413
|
+
#
|
414
|
+
# Returns a Boolean.
|
415
|
+
def suspend_file_exists?
|
416
|
+
File.file? File.join(path, "#{@name}.vmem")
|
417
|
+
end
|
418
|
+
|
419
|
+
# Public: Determines if a VM is running.
|
420
|
+
#
|
421
|
+
# Examples
|
422
|
+
#
|
423
|
+
# @vm.running?.data
|
424
|
+
# # => true
|
425
|
+
#
|
426
|
+
# Returns a Response with the result.
|
427
|
+
# If successful, the Response's data attribute will be a Boolean.
|
428
|
+
# If there is an error, an unsuccessful Response will be returned.
|
429
|
+
def running?
|
430
|
+
all_running_response = self.class.all_running
|
431
|
+
return all_running_response unless all_running_response.successful?
|
432
|
+
|
433
|
+
response = Response.new :code => 0, :data => false
|
434
|
+
|
435
|
+
if all_running_response.data.collect { |v| v.name }.include? @name
|
436
|
+
response.data = true
|
83
437
|
end
|
438
|
+
|
439
|
+
response
|
84
440
|
end
|
85
441
|
|
442
|
+
# Public: Determines the path to the VM's config file ('.vmx').
|
443
|
+
#
|
444
|
+
# Examples
|
445
|
+
#
|
446
|
+
# @vm.conf_file.data
|
447
|
+
# # => '/my_vms/foo/foo.vmx'
|
448
|
+
#
|
449
|
+
# Returns a Response with the result.
|
450
|
+
# If successful, the Response's data attribute will be a String which will
|
451
|
+
# be escaped for spaces (' ').
|
452
|
+
# If there is a single '.vmx' file in the VM's directory, regardless if
|
453
|
+
# the name of '.vmx' file matches the VM name, the Response's data
|
454
|
+
# attribute will the be the path to the '.vmx' file.
|
455
|
+
# If there are multiple '.vmx' files found in the VM's directory, there are
|
456
|
+
# a couple of different possible outcomes.
|
457
|
+
# If one of the file names matches the VM directory name, then the
|
458
|
+
# Response's data attribute will be the path to the matching '.vmx' file.
|
459
|
+
# If none of the file names match the VM directory name, then this is deemed
|
460
|
+
# an error condition and an unsuccessful Response will be returned.
|
461
|
+
# If there is an error, an unsuccessful Response will be returned.
|
86
462
|
def conf_file
|
87
|
-
vmx_path = File.join
|
88
|
-
conf_files = Dir.glob
|
463
|
+
vmx_path = File.join path, "*.vmx"
|
464
|
+
conf_files = Dir.glob vmx_path
|
465
|
+
|
466
|
+
response = Response.new
|
89
467
|
|
90
468
|
case conf_files.count
|
91
469
|
when 0
|
92
|
-
|
470
|
+
response.code = 1
|
471
|
+
response.message = "Unable to find a config file for VM '#{@name}' (in '#{vmx_path}')"
|
93
472
|
when 1
|
94
|
-
|
473
|
+
response.code = 0
|
474
|
+
response.data = conf_files.first
|
95
475
|
else
|
96
476
|
if conf_files.include?(File.join(File.dirname(vmx_path), "#{@name}.vmx"))
|
97
|
-
|
477
|
+
response.code = 0
|
478
|
+
response.data = File.join(File.dirname(vmx_path), "#{@name}.vmx")
|
98
479
|
else
|
480
|
+
response.code = 1
|
99
481
|
output = "Multiple config files found for VM '#{@name}' ("
|
100
482
|
output << conf_files.sort.map { |f| "'#{File.basename(f)}'" }.join(', ')
|
101
483
|
output << " in '#{File.dirname(vmx_path)}')"
|
102
|
-
|
484
|
+
response.message = output
|
103
485
|
end
|
104
486
|
end
|
487
|
+
|
488
|
+
response.data.gsub! ' ', '\ ' if response.successful?
|
489
|
+
|
490
|
+
response
|
105
491
|
end
|
106
492
|
|
493
|
+
# Public: Provides the expected path to a VM's directory. This does not
|
494
|
+
# imply that the VM or path exists.
|
495
|
+
#
|
496
|
+
# name - The name of the VM to provide the path for.
|
497
|
+
#
|
498
|
+
# Examples
|
499
|
+
#
|
500
|
+
# @vm.path
|
501
|
+
# # => '/vm/foo.vmwarevm'
|
502
|
+
#
|
503
|
+
# Returns the path (String) to the VM's directory.
|
504
|
+
def path
|
505
|
+
File.join Fission.config['vm_dir'], "#{@name}.vmwarevm"
|
506
|
+
end
|
507
|
+
|
508
|
+
# Public: Provides all of the VMs which are located in the VM directory.
|
509
|
+
#
|
510
|
+
# Examples
|
511
|
+
#
|
512
|
+
# Fission::VM.all.data
|
513
|
+
# # => [<Fission::VM:0x007fd6fa24c5d8 @name="foo">,
|
514
|
+
# <Fission::VM:0x007fd6fa23c5e8 @name="bar">]
|
515
|
+
#
|
516
|
+
# Returns a Response with the result.
|
517
|
+
# If successful, the Response's data attribute will be an Array of VM
|
518
|
+
# objects. If no VMs are found, the Response's data attribute will be an
|
519
|
+
# empty Array.
|
520
|
+
# If there is an error, an unsuccessful Response will be returned.
|
107
521
|
def self.all
|
108
|
-
vm_dirs = Dir[File.join Fission.config
|
522
|
+
vm_dirs = Dir[File.join Fission.config['vm_dir'], '*.vmwarevm'].select do |d|
|
109
523
|
File.directory? d
|
110
524
|
end
|
111
525
|
|
112
|
-
|
526
|
+
response = Response.new :code => 0
|
527
|
+
response.data = vm_dirs.collect { |d| new(File.basename d, '.vmwarevm') }
|
528
|
+
|
529
|
+
response
|
113
530
|
end
|
114
531
|
|
532
|
+
# Public: Provides all of the VMs which are currently running.
|
533
|
+
#
|
534
|
+
# Examples
|
535
|
+
#
|
536
|
+
# Fission::VM.all_running.data
|
537
|
+
# # => [<Fission::VM:0x007fd6fa24c5d8 @name="foo">,
|
538
|
+
# <Fission::VM:0x007fd6fa23c5e8 @name="bar">]
|
539
|
+
#
|
540
|
+
# Returns a Response with the result.
|
541
|
+
# If successful, the Response's data attribute will be an Array of VM
|
542
|
+
# objects which are running. If no VMs are running, the Response's data
|
543
|
+
# attribute will be an empty Array.
|
544
|
+
# If there is an error, an unsuccessful Response will be returned.
|
115
545
|
def self.all_running
|
116
|
-
command = "#{Fission.config
|
546
|
+
command = "#{Fission.config['vmrun_cmd']} list"
|
117
547
|
|
118
548
|
output = `#{command}`
|
119
549
|
|
120
|
-
|
550
|
+
response = Response.new :code => $?.exitstatus
|
551
|
+
|
552
|
+
if response.successful?
|
121
553
|
vms = output.split("\n").select do |vm|
|
122
554
|
vm.include?('.vmx') && File.exists?(vm) && File.extname(vm) == '.vmx'
|
123
555
|
end
|
124
556
|
|
125
|
-
vms.
|
557
|
+
response.data = vms.collect do |vm|
|
558
|
+
new File.basename(File.dirname(vm), '.vmwarevm')
|
559
|
+
end
|
126
560
|
else
|
127
|
-
|
561
|
+
response.message = output
|
128
562
|
end
|
129
|
-
end
|
130
563
|
|
131
|
-
|
132
|
-
File.directory? path(vm_name)
|
564
|
+
response
|
133
565
|
end
|
134
566
|
|
135
|
-
|
136
|
-
|
137
|
-
|
567
|
+
# Public: Creates a new VM which is a clone of an existing VM. As Fusion
|
568
|
+
# doesn't provide a native cloning mechanism, this is a best effort. This
|
569
|
+
# essentially is a directory copy with updates to relevant files. It's
|
570
|
+
# recommended to clone VMs which are not running.
|
571
|
+
#
|
572
|
+
# source_vm_name - The name of the VM to clone.
|
573
|
+
# target_vm_name - The name of the VM to be created.
|
574
|
+
#
|
575
|
+
# Examples
|
576
|
+
#
|
577
|
+
# Fission::VM.clone 'foo', 'bar'
|
578
|
+
#
|
579
|
+
# Returns a Response with the result.
|
580
|
+
# If successful, the Response's data attribute will be nil.
|
581
|
+
# If there is an error, an unsuccessful Response will be returned.
|
582
|
+
def self.clone(source_vm_name, target_vm_name)
|
583
|
+
source_vm = new source_vm_name
|
584
|
+
target_vm = new target_vm_name
|
585
|
+
|
586
|
+
unless source_vm.exists?
|
587
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
588
|
+
end
|
589
|
+
|
590
|
+
if target_vm.exists?
|
591
|
+
return Response.new :code => 1, :message => 'VM already exists'
|
592
|
+
end
|
138
593
|
|
139
|
-
|
140
|
-
Fission.ui.output "Cloning #{source_vm} to #{target_vm}"
|
141
|
-
FileUtils.cp_r path(source_vm), path(target_vm)
|
594
|
+
FileUtils.cp_r source_vm.path, target_vm.path
|
142
595
|
|
143
|
-
|
144
|
-
|
145
|
-
|
596
|
+
rename_vm_files source_vm.name, target_vm.name
|
597
|
+
update_config source_vm.name, target_vm.name
|
598
|
+
|
599
|
+
Response.new :code => 0
|
146
600
|
end
|
147
601
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
602
|
+
# Public: Deletes a VM. The VM must not be running in order to delete it.
|
603
|
+
# As there are a number issues with the Fusion command line tool for
|
604
|
+
# deleting VMs, this is a best effort. The VM must not be running when this
|
605
|
+
# method is called. This essentially deletes the VM directory and attempts
|
606
|
+
# to remove the relevant entries from the Fusion plist file. It's highly
|
607
|
+
# recommended to delete VMs without the Fusion GUI running. If the Fusion
|
608
|
+
# GUI is running this method should succeed, but it's been observed that
|
609
|
+
# Fusion will recreate the plist data which is deleted. This leads to
|
610
|
+
# 'missing' VMs in the Fusion GUI.
|
611
|
+
#
|
612
|
+
# Examples
|
613
|
+
#
|
614
|
+
# @vm.delete
|
615
|
+
#
|
616
|
+
# Returns a Response with the result.
|
617
|
+
# If successful, the Response's data attribute will be nil.
|
618
|
+
# If there is an error, an unsuccessful Response will be returned.
|
619
|
+
def delete
|
620
|
+
unless exists?
|
621
|
+
return Response.new :code => 1, :message => 'VM does not exist'
|
622
|
+
end
|
623
|
+
|
624
|
+
running_response = running?
|
625
|
+
return running_response unless running_response.successful?
|
626
|
+
|
627
|
+
if running_response.data
|
628
|
+
message = 'The VM must not be running in order to delete it.'
|
629
|
+
return Response.new :code => 1, :message => message
|
630
|
+
end
|
631
|
+
|
632
|
+
FileUtils.rm_rf path
|
633
|
+
Metadata.delete_vm_info path
|
634
|
+
|
635
|
+
Response.new :code => 0
|
152
636
|
end
|
153
637
|
|
154
638
|
private
|
639
|
+
# Internal: Renames the files of a newly cloned VM.
|
640
|
+
#
|
641
|
+
# from - The VM name that was used as the source of the clone.
|
642
|
+
# to - The name of the newly cloned VM.
|
643
|
+
#
|
644
|
+
# Examples
|
645
|
+
#
|
646
|
+
# Fission::VM.rename_vm_files 'foo', 'bar'
|
647
|
+
#
|
648
|
+
# Returns nothing.
|
155
649
|
def self.rename_vm_files(from, to)
|
650
|
+
to_vm = new to
|
651
|
+
|
156
652
|
files_to_rename(from, to).each do |file|
|
157
653
|
text_to_replace = File.basename(file, File.extname(file))
|
158
654
|
|
@@ -162,18 +658,34 @@ module Fission
|
|
162
658
|
end
|
163
659
|
end
|
164
660
|
|
165
|
-
unless File.exists?(File.join(path
|
166
|
-
FileUtils.mv File.join(path
|
167
|
-
File.join(path
|
661
|
+
unless File.exists?(File.join(to_vm.path, file.gsub(text_to_replace, to)))
|
662
|
+
FileUtils.mv File.join(to_vm.path, file),
|
663
|
+
File.join(to_vm.path, file.gsub(text_to_replace, to))
|
168
664
|
end
|
169
665
|
end
|
170
666
|
end
|
171
667
|
|
668
|
+
# Internal: Provides the list of files which need to be renamed in a newly
|
669
|
+
# cloned VM directory.
|
670
|
+
#
|
671
|
+
# from - The VM name that was used as the source of the clone.
|
672
|
+
# to - The name of the newly cloned VM.
|
673
|
+
#
|
674
|
+
# Examples
|
675
|
+
#
|
676
|
+
# Fission::VM.files_to_rename 'foo', 'bar'
|
677
|
+
# # => ['/vms/vm1/foo.vmdk', '/vms/vm1/foo.vmx', 'vms/vm1/blah.other']
|
678
|
+
#
|
679
|
+
# Returns an Array containing the paths (String) to the files to rename.
|
680
|
+
# The paths which match the from name will preceed any other files found in
|
681
|
+
# the newly cloned VM directory.
|
172
682
|
def self.files_to_rename(from, to)
|
683
|
+
to_vm = new to
|
684
|
+
|
173
685
|
files_which_match_source_vm = []
|
174
686
|
other_files = []
|
175
687
|
|
176
|
-
Dir.entries(path
|
688
|
+
Dir.entries(to_vm.path).each do |f|
|
177
689
|
unless f == '.' || f == '..'
|
178
690
|
f.include?(from) ? files_which_match_source_vm << f : other_files << f
|
179
691
|
end
|
@@ -182,19 +694,85 @@ module Fission
|
|
182
694
|
files_which_match_source_vm + other_files
|
183
695
|
end
|
184
696
|
|
697
|
+
# Internal: Provides the list of file extensions for VM related files.
|
698
|
+
#
|
699
|
+
# Examples
|
700
|
+
#
|
701
|
+
# Fission::VM.vm_file_extension
|
702
|
+
# # => ['.nvram', '.vmdk', '.vmem']
|
703
|
+
#
|
704
|
+
# Returns an Array containing the file extensions of VM realted files.
|
705
|
+
# The file extensions returned are Strings and include a '.'.
|
185
706
|
def self.vm_file_extensions
|
186
707
|
['.nvram', '.vmdk', '.vmem', '.vmsd', '.vmss', '.vmx', '.vmxf']
|
187
708
|
end
|
188
709
|
|
710
|
+
# Internal: Updates config files for a newly cloned VM. This will update any
|
711
|
+
# files with the extension of '.vmx', '.vmxf', and '.vmdk'. Any binary
|
712
|
+
# '.vmdk' files will be skipped.
|
713
|
+
#
|
714
|
+
# from - The VM name that was used as the source of the clone.
|
715
|
+
# to - The name of the newly cloned VM.
|
716
|
+
#
|
717
|
+
# Examples
|
718
|
+
#
|
719
|
+
# Fission::VM.update_config 'foo', 'bar'
|
720
|
+
#
|
721
|
+
# Returns nothing.
|
189
722
|
def self.update_config(from, to)
|
723
|
+
to_vm = new to
|
724
|
+
|
190
725
|
['.vmx', '.vmxf', '.vmdk'].each do |ext|
|
191
|
-
file = File.join path
|
726
|
+
file = File.join to_vm.path, "#{to}#{ext}"
|
192
727
|
|
193
728
|
unless File.binary?(file)
|
194
729
|
text = (File.read file).gsub from, to
|
195
730
|
File.open(file, 'w'){ |f| f.print text }
|
196
731
|
end
|
732
|
+
|
733
|
+
clean_up_conf_file(file) if ext == '.vmx'
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
# Internal: Cleans up the conf file (*.vmx) for a newly cloned VM. This
|
738
|
+
# includes removing generated MAC addresses, setting up for a new UUID, and
|
739
|
+
# disable VMware tools warning.
|
740
|
+
#
|
741
|
+
# conf_file_path - Aboslute path to the VM's conf file (.vmx).
|
742
|
+
#
|
743
|
+
# Examples
|
744
|
+
#
|
745
|
+
# VM.clean_up_conf_file '/vms/foo/foo.vmx'
|
746
|
+
#
|
747
|
+
# Returns nothing.
|
748
|
+
def self.clean_up_conf_file(conf_file_path)
|
749
|
+
conf_items_patterns = [ /^tools\.remindInstall.*\n/,
|
750
|
+
/^uuid\.action.*\n/,
|
751
|
+
/^ethernet\.+generatedAddress.*\n/ ]
|
752
|
+
|
753
|
+
content = File.read conf_file_path
|
754
|
+
|
755
|
+
conf_items_patterns.each do |pattern|
|
756
|
+
content.gsub(pattern, '').strip
|
197
757
|
end
|
758
|
+
|
759
|
+
content << "\n"
|
760
|
+
content << "tools.remindInstall = \"FALSE\"\n"
|
761
|
+
content << "uuid.action = \"create\"\n"
|
762
|
+
|
763
|
+
File.open(conf_file_path, 'w') { |f| f.print content }
|
764
|
+
end
|
765
|
+
|
766
|
+
# Internal: Helper for getting the configured vmrun_cmd value.
|
767
|
+
#
|
768
|
+
# Examples
|
769
|
+
#
|
770
|
+
# @vm.vmrun_cmd
|
771
|
+
# # => "/foo/bar/vmrun -T fusion"
|
772
|
+
#
|
773
|
+
# Returns a String for the configured value of Fission.config['vmrun_cmd'].
|
774
|
+
def vmrun_cmd
|
775
|
+
Fission.config['vmrun_cmd']
|
198
776
|
end
|
199
777
|
|
200
778
|
end
|