openstudio-workflow 1.0.0.pat1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +16 -68
- data/Rakefile +9 -9
- data/bin/openstudio_cli +786 -0
- data/lib/openstudio/workflow/adapters/input/local.rb +97 -0
- data/lib/openstudio/workflow/adapters/output/local.rb +90 -0
- data/lib/openstudio/workflow/adapters/output/socket.rb +70 -0
- data/lib/openstudio/workflow/{jobs/run_preflight/run_preflight.rb → adapters/output/web.rb} +37 -19
- data/lib/openstudio/workflow/{adapter.rb → adapters/output_adapter.rb} +53 -51
- data/lib/openstudio/workflow/job.rb +22 -0
- data/lib/openstudio/workflow/jobs/{run_energyplus → resources}/monthly_report.idf +0 -0
- data/lib/openstudio/workflow/jobs/run_energyplus.rb +49 -0
- data/lib/openstudio/workflow/jobs/run_ep_measures.rb +55 -0
- data/lib/openstudio/workflow/jobs/run_initialization.rb +136 -0
- data/lib/openstudio/workflow/jobs/run_os_measures.rb +59 -0
- data/lib/openstudio/workflow/jobs/run_postprocess.rb +53 -0
- data/lib/openstudio/workflow/jobs/run_preprocess.rb +81 -0
- data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +86 -0
- data/lib/openstudio/workflow/jobs/run_translation.rb +49 -0
- data/lib/openstudio/workflow/multi_delegator.rb +1 -3
- data/lib/openstudio/workflow/registry.rb +137 -0
- data/lib/openstudio/workflow/run.rb +182 -221
- data/lib/openstudio/workflow/time_logger.rb +1 -1
- data/lib/openstudio/workflow/util/energyplus.rb +564 -0
- data/lib/openstudio/workflow/util/io.rb +33 -0
- data/lib/openstudio/workflow/util/measure.rb +520 -0
- data/lib/openstudio/workflow/util/model.rb +100 -0
- data/lib/openstudio/workflow/util/post_process.rb +177 -0
- data/lib/openstudio/workflow/util/weather_file.rb +108 -0
- data/lib/openstudio/workflow/util.rb +14 -0
- data/lib/openstudio/workflow/version.rb +1 -1
- data/lib/openstudio/workflow_json.rb +399 -0
- data/lib/openstudio/workflow_runner.rb +213 -0
- data/lib/openstudio-workflow.rb +13 -118
- metadata +45 -85
- data/lib/openstudio/extended_runner.rb +0 -105
- data/lib/openstudio/workflow/adapters/local.rb +0 -101
- data/lib/openstudio/workflow/adapters/mongo.rb +0 -227
- data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +0 -253
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +0 -314
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +0 -230
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +0 -110
- data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +0 -471
- data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +0 -247
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +0 -279
data/bin/openstudio_cli
ADDED
@@ -0,0 +1,786 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
######################################################################
|
4
|
+
# Copyright (c) 2008-2016, Alliance for Sustainable Energy.
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# This library is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation; either
|
10
|
+
# version 2.1 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public
|
18
|
+
# License along with this library; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20
|
+
######################################################################
|
21
|
+
|
22
|
+
Signal.trap('INT') { abort }
|
23
|
+
|
24
|
+
require 'openstudio-workflow'
|
25
|
+
require 'optparse'
|
26
|
+
require 'irb'
|
27
|
+
require 'json'
|
28
|
+
include OpenStudio::Workflow::Util::IO
|
29
|
+
include OpenStudio::Workflow::Util::Directory
|
30
|
+
|
31
|
+
$logger = Logger.new(STDOUT)
|
32
|
+
$logger.level = Logger::WARN
|
33
|
+
|
34
|
+
# This is the code chunk to allow for an embedded IRB shell. From Jason Roelofs, found on StackOverflow
|
35
|
+
module IRB # :nodoc:
|
36
|
+
def self.start_session(binding)
|
37
|
+
unless @__initialized
|
38
|
+
args = ARGV
|
39
|
+
ARGV.replace(ARGV.dup)
|
40
|
+
IRB.setup(nil)
|
41
|
+
ARGV.replace(args)
|
42
|
+
@__initialized = true
|
43
|
+
end
|
44
|
+
|
45
|
+
workspace = WorkSpace.new(binding)
|
46
|
+
|
47
|
+
irb = Irb.new(workspace)
|
48
|
+
|
49
|
+
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
|
50
|
+
@CONF[:MAIN_CONTEXT] = irb.context
|
51
|
+
|
52
|
+
catch(:IRB_EXIT) do
|
53
|
+
irb.eval_input
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# This is the save puts to use to catch EPIPE. Uses `puts` on the given IO object and safely ignores any Errno::EPIPE
|
59
|
+
#
|
60
|
+
# @param [String] message Message to output
|
61
|
+
# @param [Hash] opts Options hash
|
62
|
+
#
|
63
|
+
def safe_puts(message = nil, opts = nil)
|
64
|
+
message ||= ''
|
65
|
+
opts = {
|
66
|
+
io: $stdout,
|
67
|
+
printer: :puts
|
68
|
+
}.merge(opts || {})
|
69
|
+
|
70
|
+
begin
|
71
|
+
opts[:io].send(opts[:printer], message)
|
72
|
+
rescue Errno::EPIPE
|
73
|
+
# This is what makes this a `safe` puts
|
74
|
+
return
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# This is a convenience method that properly handles duping the originally argv array so that it is not destroyed. This
|
79
|
+
# method will also automatically detect "-h" and "--help" and print help. And if any invalid options are detected, the
|
80
|
+
# help will be printed, as well
|
81
|
+
#
|
82
|
+
# @param [Object, nil] opts An instance of OptionParse to parse against, defaults to a new OptionParse instance
|
83
|
+
# @param [Array, nil] argv The argv input to be parsed, defaults to $argv
|
84
|
+
# @return[Array, nil] If this method returns `nil`, then you should assume that help was printed and parsing failed
|
85
|
+
#
|
86
|
+
def parse_options(opts = nil, argv = nil)
|
87
|
+
# Creating a shallow copy of the arguments so the OptionParser
|
88
|
+
# doesn't destroy the originals.
|
89
|
+
argv ||= $argv.dup
|
90
|
+
|
91
|
+
# Default opts to a blank optionparser if none is given
|
92
|
+
opts ||= OptionParser.new
|
93
|
+
|
94
|
+
# Add the help option, which must be on every command.
|
95
|
+
opts.on_tail('-h', '--help', 'Print this help') do
|
96
|
+
safe_puts(opts.help)
|
97
|
+
return nil
|
98
|
+
end
|
99
|
+
|
100
|
+
opts.parse!(argv)
|
101
|
+
return argv
|
102
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
103
|
+
raise "Error: Invalid CLI option, #{opts.help.chomp}"
|
104
|
+
end
|
105
|
+
|
106
|
+
# This method will split the argv given into three parts: the flags to this command, the subcommand, and the flags to
|
107
|
+
# the subcommand. For example:
|
108
|
+
# -v status -h -v
|
109
|
+
# The above would yield 3 parts:
|
110
|
+
# ["-v"]
|
111
|
+
# "status"
|
112
|
+
# ["-h", "-v"]
|
113
|
+
# These parts are useful because the first is a list of arguments given to the current command, the second is a
|
114
|
+
# subcommand, and the third are the commands given to the subcommand
|
115
|
+
#
|
116
|
+
# @param [Array] argv The input to be split
|
117
|
+
# @return [Array] The split command as [main arguments, sub command, sub command arguments]
|
118
|
+
#
|
119
|
+
def split_main_and_subcommand(argv)
|
120
|
+
# Initialize return variables
|
121
|
+
main_args = nil
|
122
|
+
sub_command = nil
|
123
|
+
sub_args = []
|
124
|
+
|
125
|
+
# We split the arguments into two: One set containing any flags before a word, and then the rest. The rest are what
|
126
|
+
# get actually sent on to the subcommand
|
127
|
+
argv.each_index do |i|
|
128
|
+
unless argv[i].start_with?('-')
|
129
|
+
# We found the beginning of the sub command. Split the
|
130
|
+
# args up.
|
131
|
+
main_args = argv[0, i]
|
132
|
+
sub_command = argv[i]
|
133
|
+
sub_args = argv[i + 1, argv.length - i + 1]
|
134
|
+
|
135
|
+
# Break so we don't find the next non flag and shift our main args
|
136
|
+
break
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Handle the case that argv was empty or didn't contain any subcommand
|
141
|
+
main_args = argv.dup if main_args.nil?
|
142
|
+
|
143
|
+
[main_args, sub_command, sub_args]
|
144
|
+
end
|
145
|
+
|
146
|
+
# This CLI class processes the input args and invokes the proper command class
|
147
|
+
class CLI
|
148
|
+
# This constant maps subcommands to classes in this CLI and stores meta-data on them
|
149
|
+
COMMAND_LIST = {
|
150
|
+
run: [proc { ::Run }, { primary: true, working: true }],
|
151
|
+
apply_measure: [proc { ::ApplyMeasure }, { primary: true, working: false }],
|
152
|
+
gem_list: [proc { ::GemList }, { primary: true, working: true }],
|
153
|
+
gem_install: [proc { ::InstallGem }, { primary: false, working: true }],
|
154
|
+
measure: [proc { ::Measure }, { primary: true, working: false }],
|
155
|
+
e: [proc { ::ExecuteRubyScript }, { primary: false, working: true }],
|
156
|
+
i: [proc { ::InteractiveRubyShell }, { primary: false, working: true }],
|
157
|
+
openstudio_version: [proc { ::OpenStudioVersion }, { primary: true, working: true }],
|
158
|
+
energyplus_version: [proc { ::EnergyPlusVersion }, { primary: true, working: true }],
|
159
|
+
ruby_version: [proc { ::RubyVersion }, { primary: false, working: true }],
|
160
|
+
list_commands: [proc { ::ListCommands }, { primary: true, working: true }]
|
161
|
+
}.freeze
|
162
|
+
|
163
|
+
# This method instantiates the global variables $main_args, $sub_command, and $sub_args
|
164
|
+
#
|
165
|
+
# @param [Array] argv The arguments passed through the CLI
|
166
|
+
# @return [Object] An instance of the CLI class with initialized globals
|
167
|
+
#
|
168
|
+
def initialize(argv)
|
169
|
+
$main_args, $sub_command, $sub_args = split_main_and_subcommand(argv)
|
170
|
+
|
171
|
+
$logger.info("CLI Parsed Inputs: #{$main_args.inspect} #{$sub_command.inspect} #{$sub_args.inspect}")
|
172
|
+
end
|
173
|
+
|
174
|
+
# Checks to see if it should print the main help, and if not parses the subcommand into a class and executes it
|
175
|
+
def execute
|
176
|
+
$logger.debug "Main arguments are #{$main_args}"
|
177
|
+
$logger.debug "Sub-command is #{$sub_command}"
|
178
|
+
$logger.debug "Sub-arguments are #{$sub_args}"
|
179
|
+
if $main_args.include?('-h') || $main_args.include?('--help')
|
180
|
+
# Help is next in short-circuiting everything. Print
|
181
|
+
# the help and exit.
|
182
|
+
help
|
183
|
+
return 0
|
184
|
+
end
|
185
|
+
|
186
|
+
# If we reached this far then we must have a subcommand. If not,
|
187
|
+
# then we also just print the help and exit.
|
188
|
+
command_plugin = nil
|
189
|
+
if $sub_command
|
190
|
+
command_plugin = COMMAND_LIST[$sub_command.to_sym]
|
191
|
+
end
|
192
|
+
|
193
|
+
if !command_plugin || !$sub_command
|
194
|
+
help
|
195
|
+
return 1
|
196
|
+
end
|
197
|
+
|
198
|
+
command_class = command_plugin[0].call
|
199
|
+
$logger.debug("Invoking command class: #{command_class} #{$sub_args.inspect}")
|
200
|
+
|
201
|
+
# Initialize and execute the command class, returning the exit status.
|
202
|
+
result = 0
|
203
|
+
begin
|
204
|
+
result = command_class.new.execute($sub_args)
|
205
|
+
rescue Interrupt
|
206
|
+
$logger.error '?'
|
207
|
+
result = 1
|
208
|
+
end
|
209
|
+
|
210
|
+
result = 0 unless result.is_a?(Fixnum)
|
211
|
+
result
|
212
|
+
end
|
213
|
+
|
214
|
+
# Prints out the help text for the CLI
|
215
|
+
#
|
216
|
+
# @param [Boolean] list_all If set to true, the help prints all commands, however it otherwise only prints those
|
217
|
+
# marked as primary in #COMMAND_LIST
|
218
|
+
# @return [void]
|
219
|
+
# @see #COMMAND_LIST #::ListCommands
|
220
|
+
#
|
221
|
+
def help(list_all = false)
|
222
|
+
opts = OptionParser.new do |o|
|
223
|
+
o.banner = 'Usage: openstudio_cli [options] <command> [<args>]'
|
224
|
+
o.separator ''
|
225
|
+
o.on('-h', '--help', 'Print this help.')
|
226
|
+
o.on('--verbose', 'Print the full log to STDOUT')
|
227
|
+
o.on('--gem_path PATH', 'Path to use for installing gems to and loading gems from')
|
228
|
+
o.separator ''
|
229
|
+
o.separator 'Common commands:'
|
230
|
+
|
231
|
+
# Add the available subcommands as separators in order to print them
|
232
|
+
# out as well.
|
233
|
+
commands = {}
|
234
|
+
longest = 0
|
235
|
+
COMMAND_LIST.each do |key, data|
|
236
|
+
# Skip non-primary commands. These only show up in extended
|
237
|
+
# help output.
|
238
|
+
next unless list_all || data[1][:primary]
|
239
|
+
|
240
|
+
key = key.to_s
|
241
|
+
klass = data[0].call
|
242
|
+
commands[key] = klass.synopsis
|
243
|
+
longest = key.length if key.length > longest
|
244
|
+
end
|
245
|
+
|
246
|
+
commands.keys.sort.each do |key|
|
247
|
+
o.separator " #{key.ljust(longest + 2)} #{commands[key]}"
|
248
|
+
end
|
249
|
+
|
250
|
+
o.separator ''
|
251
|
+
o.separator 'For help on any individual command run `openstudio_cli COMMAND -h`'
|
252
|
+
unless list_all
|
253
|
+
o.separator ''
|
254
|
+
o.separator 'Additional subcommands are available, but are either more advanced'
|
255
|
+
o.separator 'or not commonly used. To see all subcommands, run the command'
|
256
|
+
o.separator '`openstudio_cli list_commands`.'
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
safe_puts opts.help
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Class to execute part or all of an OSW workflow
|
265
|
+
class Run
|
266
|
+
# Provides text for the main help functionality
|
267
|
+
def self.synopsis
|
268
|
+
'Executes an OpenStudio Workflow file'
|
269
|
+
end
|
270
|
+
|
271
|
+
# Executes the standard, or one of two custom, workflows using the workflow-gem
|
272
|
+
#
|
273
|
+
# @param [Array] sub_argv Options passed to the run subcommand from the user input
|
274
|
+
# @return [Fixnum] Return status
|
275
|
+
#
|
276
|
+
def execute(sub_argv)
|
277
|
+
options = {}
|
278
|
+
options[:debug] = false
|
279
|
+
options[:no_simulation] = false
|
280
|
+
options[:workflow] = './workflow.osw'
|
281
|
+
options[:post_process] = false
|
282
|
+
|
283
|
+
opts = OptionParser.new do |o|
|
284
|
+
o.banner = 'Usage: openstudio_cli run [options]'
|
285
|
+
o.separator ''
|
286
|
+
o.separator 'Options:'
|
287
|
+
o.separator ''
|
288
|
+
|
289
|
+
o.on('-w', '--workflow [FILE]', 'Specify the FILE path to the workflow to run') do |workflow|
|
290
|
+
options[:workflow] = workflow
|
291
|
+
end
|
292
|
+
o.on('-m', '--measures_only', 'Only run the OpenStudio and EnergyPlus measures') do
|
293
|
+
options[:no_simulation] = true
|
294
|
+
end
|
295
|
+
o.on('-p', '--postprocess_only', 'Only run the reporting measures') do
|
296
|
+
options[:post_process] = true
|
297
|
+
end
|
298
|
+
o.on('--debug', 'Includes additional outputs for debugging failing workflows and does not clean up the run directory') do |f|
|
299
|
+
options[:debug] = f
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# Parse the options
|
304
|
+
argv = parse_options(opts, sub_argv)
|
305
|
+
return 0 if argv.nil?
|
306
|
+
unless argv == []
|
307
|
+
$logger.error 'Extra arguments passed to the run command. Please refer to the help documentation.'
|
308
|
+
return 1
|
309
|
+
end
|
310
|
+
$logger.debug("Run command: #{argv.inspect} #{options.inspect}")
|
311
|
+
|
312
|
+
if options[:post_process] && options[:no_simulation]
|
313
|
+
$logger.error 'Both the -m and -p flags were set, which is an invalid combination.'
|
314
|
+
return 1
|
315
|
+
end
|
316
|
+
|
317
|
+
osw_path = options[:workflow]
|
318
|
+
osw_path = File.absolute_path(File.join(Dir.pwd, osw_path)) unless Pathname.new(osw_path).absolute?
|
319
|
+
$logger.debug "Path for the OSW: #{osw_path}"
|
320
|
+
|
321
|
+
adapter_options = { workflow_filename: File.basename(osw_path) }
|
322
|
+
input_adapter = OpenStudio::Workflow.load_input_adapter 'local', adapter_options
|
323
|
+
adapter_options[:output_directory] = input_adapter.run_directory File.dirname(osw_path)
|
324
|
+
output_adapter = OpenStudio::Workflow.load_output_adapter 'local', adapter_options
|
325
|
+
run_options = options[:debug] ? { debug: true, cleanup: false } : {}
|
326
|
+
if options[:no_simulation]
|
327
|
+
run_options[:jobs] = [
|
328
|
+
{ state: :queued, next_state: :initialization, options: { initial: true } },
|
329
|
+
{ state: :initialization, next_state: :os_measures, job: :RunInitialization,
|
330
|
+
file: 'openstudio/workflow/jobs/run_initialization.rb', options: {} },
|
331
|
+
{ state: :os_measures, next_state: :translator, job: :RunOpenStudioMeasures,
|
332
|
+
file: 'openstudio/workflow/jobs/run_os_measures.rb', options: {} },
|
333
|
+
{ state: :translator, next_state: :ep_measures, job: :RunTranslation,
|
334
|
+
file: 'openstudio/workflow/jobs/run_translation.rb', options: {} },
|
335
|
+
{ state: :ep_measures, next_state: :finished, job: :RunEnergyPlusMeasures,
|
336
|
+
file: 'openstudio/workflow/jobs/run_ep_measures.rb', options: {} },
|
337
|
+
{ state: :finished },
|
338
|
+
{ state: :errored }
|
339
|
+
]
|
340
|
+
elsif options[:post_process]
|
341
|
+
run_options[:jobs] = [
|
342
|
+
{ state: :queued, next_state: :initialization, options: { initial: true } },
|
343
|
+
{ state: :initialization, next_state: :reporting_measures, job: :RunInitialization,
|
344
|
+
file: 'openstudio/workflow/jobs/run_initialization.rb', options: {} },
|
345
|
+
{ state: :reporting_measures, next_state: :postprocess, job: :RunReportingMeasures,
|
346
|
+
file: 'openstudio/workflow/jobs/run_reporting_measures.rb', options: {} },
|
347
|
+
{ state: :postprocess, next_state: :finished, job: :RunPostprocess,
|
348
|
+
file: 'openstudio/workflow/jobs/run_postprocess.rb', options: {} },
|
349
|
+
{ state: :finished },
|
350
|
+
{ state: :errored }
|
351
|
+
]
|
352
|
+
run_options[:load_simulation_osm] = true
|
353
|
+
run_options[:load_simulation_idf] = true
|
354
|
+
run_options[:load_simulation_sql] = true
|
355
|
+
run_options[:preserve_run_dir] = true
|
356
|
+
end
|
357
|
+
k = OpenStudio::Workflow::Run.new input_adapter, output_adapter, File.dirname(osw_path), run_options
|
358
|
+
k.run
|
359
|
+
|
360
|
+
0
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# Class to apply an OpenStudio, EnergyPlus, or Reporting measure
|
365
|
+
# @abstract
|
366
|
+
class ApplyMeasure
|
367
|
+
# Provides text for the main help functionality
|
368
|
+
def self.synopsis
|
369
|
+
'Applies an OpenStudio, EnergyPlus, or Reporting measure'
|
370
|
+
end
|
371
|
+
|
372
|
+
# Executes a single measure using an undefined interface
|
373
|
+
#
|
374
|
+
# @param [Array] sub_argv Options passed to the apply_measures subcommand from the user input
|
375
|
+
# @return [Fixnum] Return status
|
376
|
+
# @abstract
|
377
|
+
#
|
378
|
+
def execute(sub_argv)
|
379
|
+
# options = {}
|
380
|
+
# options[:debug] = false
|
381
|
+
|
382
|
+
# opts = OptionParser.new do |o|
|
383
|
+
# o.banner = 'Usage: openstudio_cli apply_measure'
|
384
|
+
# o.separator ''
|
385
|
+
# o.separator 'Options:'
|
386
|
+
# o.separator ''
|
387
|
+
# end
|
388
|
+
|
389
|
+
$logger.error 'This interface has yet to be defined.'
|
390
|
+
|
391
|
+
# Parse the options
|
392
|
+
argv = parse_options(opts, sub_argv)
|
393
|
+
return 1 unless argv
|
394
|
+
# $logger.debug("ApplyMeasure command: #{argv.inspect} #{options.inspect}")
|
395
|
+
|
396
|
+
1
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
# Class to list the gems used by the CLI
|
401
|
+
class GemList
|
402
|
+
# Provides text for the main help functionality
|
403
|
+
def self.synopsis
|
404
|
+
'Lists the set gems available to openstudio_cli'
|
405
|
+
end
|
406
|
+
|
407
|
+
# Alters the environment variable used to define the gem install location
|
408
|
+
#
|
409
|
+
# @param [Array] sub_argv Options passed to the gem_install subcommand from the user input
|
410
|
+
# @return [Fixnum] Return status
|
411
|
+
#
|
412
|
+
def execute(sub_argv)
|
413
|
+
require 'rubygems'
|
414
|
+
require 'rubygems/gem_runner'
|
415
|
+
|
416
|
+
# Parse the options
|
417
|
+
opts = OptionParser.new do |o|
|
418
|
+
o.banner = 'Usage: openstudio_cli gem_list'
|
419
|
+
end
|
420
|
+
argv = parse_options(opts, sub_argv)
|
421
|
+
unless argv == []
|
422
|
+
$logger.error 'Extra arguments passed to the gem_list command. Please refer to the help documentation.'
|
423
|
+
return 1
|
424
|
+
end
|
425
|
+
|
426
|
+
begin
|
427
|
+
Gem::GemRunner.new.run ['list']
|
428
|
+
rescue => e
|
429
|
+
$logger.error "Error listing gems: #{e.message} in #{e.backtrace.join("\n")}"
|
430
|
+
exit e.exit_code
|
431
|
+
end
|
432
|
+
|
433
|
+
0
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
# Class to install gems using the RubyGems functionality
|
438
|
+
class InstallGem
|
439
|
+
# Provides text for the main help functionality
|
440
|
+
def self.synopsis
|
441
|
+
'Installs a Gem using the embedded ruby'
|
442
|
+
end
|
443
|
+
|
444
|
+
# Executes the RubyGems gem install process, using the RubyGems options
|
445
|
+
#
|
446
|
+
# @param [Array] sub_argv Options passed to the gem_install subcommand from the user input
|
447
|
+
# @return [Fixnum] Return status
|
448
|
+
#
|
449
|
+
def execute(sub_argv)
|
450
|
+
require 'rubygems'
|
451
|
+
require 'rubygems/gem_runner'
|
452
|
+
|
453
|
+
# Parse the options
|
454
|
+
argv = sub_argv.unshift('install')
|
455
|
+
if argv.include? '--install-dir'
|
456
|
+
$logger.error 'The rubygems option --install-dir is not supported. Please use the --gem_path option'
|
457
|
+
return 1
|
458
|
+
else
|
459
|
+
argv.push '--install-dir'
|
460
|
+
argv.push ENV['GEM_PATH']
|
461
|
+
end
|
462
|
+
$logger.debug "GemInstall command: #{argv.inspect}"
|
463
|
+
$logger.debug "Invoking the GemRunner with argv: #{argv}"
|
464
|
+
|
465
|
+
begin
|
466
|
+
Gem::GemRunner.new.run argv
|
467
|
+
rescue => e
|
468
|
+
$logger.error "Error installing gem: #{e.message} in #{e.backtrace.join("\n")}"
|
469
|
+
exit e.exit_code
|
470
|
+
end
|
471
|
+
|
472
|
+
$logger.info 'The gem was successfully installed'
|
473
|
+
|
474
|
+
0
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
# Class to update measures and compute arguments
|
479
|
+
class Measure
|
480
|
+
# Provides text for the main help functionality
|
481
|
+
def self.synopsis
|
482
|
+
'Updates measures and compute arguments'
|
483
|
+
end
|
484
|
+
|
485
|
+
# Executes code to update and compute arguments for measures
|
486
|
+
#
|
487
|
+
# @param [Array] sub_argv Options passed to the e subcommand from the user input
|
488
|
+
# @return [Fixnum] Return status
|
489
|
+
# @todo (macumber) Add in the OpenStudio code to execute on measures
|
490
|
+
#
|
491
|
+
def execute(sub_argv)
|
492
|
+
options = {}
|
493
|
+
options[:check_for_update] = false
|
494
|
+
options[:update] = false
|
495
|
+
options[:compute_arguments] = nil
|
496
|
+
|
497
|
+
opts = OptionParser.new do |o|
|
498
|
+
o.banner = 'Usage: openstudio_cli measure [options] DIRECTORY'
|
499
|
+
o.separator ''
|
500
|
+
o.separator 'Options:'
|
501
|
+
o.separator ''
|
502
|
+
|
503
|
+
o.on('-c', '--check_for_updates', 'Check to see if the measure needs to be updated') do
|
504
|
+
options[:check_for_update] = workflow
|
505
|
+
end
|
506
|
+
o.on('-u', '--update', 'Update the measure.xml') do
|
507
|
+
options[:update] = true
|
508
|
+
end
|
509
|
+
o.on('-a', '--compute_arguments [MODEL]', 'Compute arguments for the given model') do |model_file|
|
510
|
+
options[:compute_arguments] = model_file
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
# Parse the options
|
515
|
+
argv = parse_options(opts, sub_argv)
|
516
|
+
$logger.error 'No directory provided' if argv == []
|
517
|
+
return 1 if argv == []
|
518
|
+
directory = argv[0]
|
519
|
+
|
520
|
+
$logger.debug("Measure command: #{argv.inspect} #{options.inspect}")
|
521
|
+
$logger.debug("Directory to examine is #{directory}")
|
522
|
+
|
523
|
+
$logger.error 'Code to be added here to operate on measures'
|
524
|
+
|
525
|
+
1
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
# Class to execute a ruby script
|
530
|
+
class ExecuteRubyScript
|
531
|
+
# Provides text for the main help functionality
|
532
|
+
def self.synopsis
|
533
|
+
'Executes a ruby file'
|
534
|
+
end
|
535
|
+
|
536
|
+
# Executes an arbitrary ruby script
|
537
|
+
#
|
538
|
+
# @param [Array] sub_argv Options passed to the e subcommand from the user input
|
539
|
+
# @return [Fixnum] Return status
|
540
|
+
#
|
541
|
+
def execute(sub_argv)
|
542
|
+
options = {}
|
543
|
+
|
544
|
+
opts = OptionParser.new do |o|
|
545
|
+
o.banner = 'Usage: openstudio_cli e [file]'
|
546
|
+
end
|
547
|
+
|
548
|
+
# Parse the options
|
549
|
+
argv = parse_options(opts, sub_argv)
|
550
|
+
return 0 if argv.nil?
|
551
|
+
return 1 unless argv
|
552
|
+
$logger.debug("ExecuteRubyScript command: #{argv.inspect} #{options.inspect}")
|
553
|
+
file_path = argv.shift.to_s
|
554
|
+
file_path = File.absolute_path(File.join(Dir.pwd, file_path)) unless Pathname.new(file_path).absolute?
|
555
|
+
$logger.debug "Path for the file to run: #{file_path}"
|
556
|
+
|
557
|
+
unless argv == []
|
558
|
+
$logger.error 'Extra arguments passed to the e command. Please refer to the help documentation.'
|
559
|
+
return 1
|
560
|
+
end
|
561
|
+
|
562
|
+
unless File.exist? file_path
|
563
|
+
$logger.error "Unable to find the file #{file_path} on the filesystem"
|
564
|
+
return 1
|
565
|
+
end
|
566
|
+
|
567
|
+
require file_path
|
568
|
+
|
569
|
+
0
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
# Class to put the user into an irb shell
|
574
|
+
class InteractiveRubyShell
|
575
|
+
# Provides text for the main help functionality
|
576
|
+
def self.synopsis
|
577
|
+
'Provides an interactive ruby shell'
|
578
|
+
end
|
579
|
+
|
580
|
+
# Executes the commands to get into an IRB prompt
|
581
|
+
#
|
582
|
+
# @param [Array] sub_argv Options passed to the i subcommand from the user input
|
583
|
+
# @return [Fixnum] Return status
|
584
|
+
#
|
585
|
+
def execute(sub_argv)
|
586
|
+
options = {}
|
587
|
+
|
588
|
+
opts = OptionParser.new do |o|
|
589
|
+
o.banner = 'Usage: openstudio_cli i'
|
590
|
+
end
|
591
|
+
|
592
|
+
# Parse the options
|
593
|
+
argv = parse_options(opts, sub_argv)
|
594
|
+
$logger.debug("InteractiveRubyShell command: #{argv.inspect} #{options.inspect}")
|
595
|
+
return 0 if argv.nil?
|
596
|
+
|
597
|
+
unless argv == []
|
598
|
+
$logger.error 'Extra arguments passed to the i command.'
|
599
|
+
return 1
|
600
|
+
end
|
601
|
+
|
602
|
+
IRB.start_session(binding)
|
603
|
+
|
604
|
+
0
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
# Class to return the packaged OpenStudio version
|
609
|
+
class OpenStudioVersion
|
610
|
+
# Provides text for the main help functionality
|
611
|
+
def self.synopsis
|
612
|
+
'Returns the OpenStudio version used by the CLI'
|
613
|
+
end
|
614
|
+
|
615
|
+
# Executes the OpenStudio commands to return the OpenStudio version
|
616
|
+
#
|
617
|
+
# @param [Array] sub_argv Options passed to the energyplus_version subcommand from the user input
|
618
|
+
# @return [Fixnum] Return status
|
619
|
+
#
|
620
|
+
def execute(sub_argv)
|
621
|
+
options = {}
|
622
|
+
|
623
|
+
opts = OptionParser.new do |o|
|
624
|
+
o.banner = 'Usage: openstudio_cli openstudio_version'
|
625
|
+
end
|
626
|
+
|
627
|
+
# Parse the options
|
628
|
+
argv = parse_options(opts, sub_argv)
|
629
|
+
$logger.debug("OpenStudioVersion command: #{argv.inspect} #{options.inspect}")
|
630
|
+
return 0 if argv.nil?
|
631
|
+
|
632
|
+
unless argv == []
|
633
|
+
$logger.error 'Extra arguments passed to the openstudio_version command.'
|
634
|
+
return 1
|
635
|
+
end
|
636
|
+
|
637
|
+
safe_puts OpenStudio.openStudioLongVersion
|
638
|
+
|
639
|
+
0
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
# Class to return the EnergyPlus version
|
644
|
+
class EnergyPlusVersion
|
645
|
+
# Provides text for the main help functionality
|
646
|
+
def self.synopsis
|
647
|
+
'Returns the EnergyPlus version used by the CLI'
|
648
|
+
end
|
649
|
+
|
650
|
+
# Executes the OpenStudio command to return the EnergyPlus version
|
651
|
+
#
|
652
|
+
# @param [Array] sub_argv Options passed to the openstudio_version subcommand from the user input
|
653
|
+
# @return [Fixnum] Return status
|
654
|
+
#
|
655
|
+
def execute(sub_argv)
|
656
|
+
options = {}
|
657
|
+
|
658
|
+
opts = OptionParser.new do |o|
|
659
|
+
o.banner = 'Usage: openstudio_cli energyplus_version'
|
660
|
+
end
|
661
|
+
|
662
|
+
# Parse the options
|
663
|
+
argv = parse_options(opts, sub_argv)
|
664
|
+
$logger.debug("EnergyPlusVersion command: #{argv.inspect} #{options.inspect}")
|
665
|
+
return 0 if argv.nil?
|
666
|
+
|
667
|
+
unless argv == []
|
668
|
+
$logger.error 'Arguments passed to the energyplus_version command.'
|
669
|
+
return 1
|
670
|
+
end
|
671
|
+
|
672
|
+
safe_puts OpenStudio.energyPlusVersion
|
673
|
+
|
674
|
+
0
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
# Class to return the ruby version used by the packaged CLI
|
679
|
+
class RubyVersion
|
680
|
+
# Provides text for the main help functionality
|
681
|
+
def self.synopsis
|
682
|
+
'Returns the Ruby version used by the CLI'
|
683
|
+
end
|
684
|
+
|
685
|
+
# Evaluates the RUBY_VERSION constant and returns it
|
686
|
+
#
|
687
|
+
# @param [Array] sub_argv Options passed to the ruby_version subcommand from the user input
|
688
|
+
# @return [Fixnum] Return status
|
689
|
+
#
|
690
|
+
def execute(sub_argv)
|
691
|
+
options = {}
|
692
|
+
|
693
|
+
opts = OptionParser.new do |o|
|
694
|
+
o.banner = 'Usage: openstudio_cli ruby_version'
|
695
|
+
end
|
696
|
+
|
697
|
+
# Parse the options
|
698
|
+
argv = parse_options(opts, sub_argv)
|
699
|
+
$logger.debug("RubyVersion command: #{argv.inspect} #{options.inspect}")
|
700
|
+
return 0 if argv.nil?
|
701
|
+
|
702
|
+
unless argv == []
|
703
|
+
$logger.error 'Arguments passed to the ruby_version command.'
|
704
|
+
return 1
|
705
|
+
end
|
706
|
+
|
707
|
+
safe_puts RUBY_VERSION
|
708
|
+
|
709
|
+
0
|
710
|
+
end
|
711
|
+
end
|
712
|
+
|
713
|
+
# Class to return the full set of possible commands for the CLI
|
714
|
+
class ListCommands
|
715
|
+
# Provides text for the main help functionality
|
716
|
+
def self.synopsis
|
717
|
+
'Lists the entire set of available commands for openstudio_cli'
|
718
|
+
end
|
719
|
+
|
720
|
+
# Executes the standard help method with the list_all attribute set to true
|
721
|
+
#
|
722
|
+
# @param [Array] sub_argv Options passed to the list_all subcommand from the user input
|
723
|
+
# @return [Fixnum] Return status
|
724
|
+
# @see #::CLI.help
|
725
|
+
#
|
726
|
+
def execute(sub_argv)
|
727
|
+
options = {}
|
728
|
+
|
729
|
+
opts = OptionParser.new do |o|
|
730
|
+
o.banner = 'Usage: openstudio_cli list_commands'
|
731
|
+
end
|
732
|
+
|
733
|
+
# Parse the options
|
734
|
+
argv = parse_options(opts, sub_argv)
|
735
|
+
$logger.debug("ListCommands command: #{argv.inspect} #{options.inspect}")
|
736
|
+
return 0 if argv.nil?
|
737
|
+
|
738
|
+
unless argv == []
|
739
|
+
$logger.error 'Arguments passed to the list_commands command.'
|
740
|
+
return 1
|
741
|
+
end
|
742
|
+
|
743
|
+
$logger.debug 'Creating a new CLI instance and calling help with list_all enabled'
|
744
|
+
::CLI.new([]).help(true)
|
745
|
+
|
746
|
+
0
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
# Set the logger level to DEBUG if the arguments include --verbose
|
751
|
+
$argv = ARGV.dup
|
752
|
+
if $argv.include? '--verbose'
|
753
|
+
$logger.level = Logger::DEBUG
|
754
|
+
$argv.delete '--verbose'
|
755
|
+
$logger.debug 'Set Logger log level to DEBUG'
|
756
|
+
end
|
757
|
+
$logger.debug "Input ARGV is #{$argv}"
|
758
|
+
|
759
|
+
# Operate on the gem_path option to set the gem search path
|
760
|
+
if $argv.include? '--gem_path'
|
761
|
+
$logger.info 'Setting gem path'
|
762
|
+
option_index = $argv.index '--gem_path'
|
763
|
+
path_index = option_index + 1
|
764
|
+
new_home = $argv[path_index]
|
765
|
+
$argv.slice! path_index
|
766
|
+
$argv.slice! $argv.index '--gem_path'
|
767
|
+
current_home = ENV['OPENSTUDIO_GEM_PATH']
|
768
|
+
$logger.warn "Overwriting previous OPENSTUDIO_GEM_PATH of #{current_home} to #{new_home} for this command" if current_home
|
769
|
+
$logger.info "No current gem path set in OPENSTUDIO_GEM_PATH, setting to #{new_home}" unless current_home
|
770
|
+
ENV['OPENSTUDIO_GEM_PATH'] = new_home
|
771
|
+
end
|
772
|
+
|
773
|
+
# Configure Gems to load the correct Gem files
|
774
|
+
# @see http://rubygems.rubyforge.org/rubygems-update/Gem.html
|
775
|
+
local_dir = ENV['OPENSTUDIO_GEM_PATH'] ? ENV['OPENSTUDIO_GEM_PATH'] : "~/OpenStudio/v#{OpenStudio.openStudioVersion}"
|
776
|
+
local_dir = File.absolute_path(local_dir)
|
777
|
+
ENV['GEM_PATH'] = OpenStudio::Workflow::Util::IO.is_windows? ? local_dir.tr('/', '\\') : local_dir
|
778
|
+
$logger.debug "Set environment variable GEM_PATH to #{ENV['GEM_PATH']}"
|
779
|
+
ENV['GEM_HOME'] = OpenStudio::Workflow::Util::IO.is_windows? ? '\\' : '/'
|
780
|
+
$logger.debug "Set environment variable GEM_HOME to #{ENV['GEM_HOME']}"
|
781
|
+
Gem.clear_paths
|
782
|
+
$logger.debug 'Reset Gem paths; openstudio_cli associated gems should load correctly'
|
783
|
+
|
784
|
+
# Execute the CLI interface, and exit with the proper error code
|
785
|
+
$logger.info "Executing argv: #{$argv}"
|
786
|
+
CLI.new($argv).execute
|