forj 0.0.30 → 0.0.31

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -4,6 +4,15 @@ Forj cli
4
4
 
5
5
  Installation
6
6
  =====================
7
+ For ruby 2.0
8
+ Fedora/CentOS/Redhat/rpm like system :
9
+ sudo yum install ruby-dev build-essential libopenssl-ruby libssl-dev zlib1g-dev -y
10
+ sudo gem install forj
11
+
12
+ Ubuntu/Debian/debian like system (not tested)
13
+ sudo apt-get install ruby-dev build-essential libopenssl-ruby1.9.1 libssl-dev zlib1g-dev -y
14
+ sudo gem install forj
15
+
7
16
  For ruby 1.9
8
17
 
9
18
  sudo apt-get install ruby-dev build-essential libopenssl-ruby1.9.1 libssl-dev zlib1g-dev -y
@@ -59,4 +68,4 @@ your development today!
59
68
 
60
69
  License
61
70
  =====================
62
- Forj Cli is licensed under the Apache License, Version 2.0. See LICENSE for full license text.
71
+ Forj Cli is licensed under the Apache License, Version 2.0. See LICENSE for full license text.
data/bin/forj CHANGED
@@ -78,12 +78,13 @@ class Forj < Thor
78
78
  method_option :build_config_dir, :aliases => '-d', :desc => 'Defines the build configuration directory to load the build configuration file. You can set FORJ_BLD_CONF_DIR. By default, it will look in your current directory.'
79
79
  method_option :build_config, :aliases => '-c', :desc => 'The build config file to load <confdir>/<BoxName>.<Config>.env. By default, uses "master" as Config.'
80
80
  method_option :branch, :aliases => '-b', :desc => 'The build will extract from git branch name. It sets the configuration build <config> to the branch name <branch>.'
81
- method_option :test_box, :aliases => '-t', :desc => 'Create test-box meta from the repository path provided.'
81
+ method_option :test_box, :aliases => '-t', :desc => 'Create test.rb-box meta from the repository path provided.'
82
82
  method_option :git_repo, :aliases => '-r', :desc => 'The box built will use a different git repository sent out to <user_data>. This repository needs to be read only. No keys are sent.'
83
83
  method_option :boothook, :aliases => '-h', :desc => 'By default, boothook file used is build/bin/build-tools/boothook.sh. Use this option to set another one.'
84
84
  method_option :box_name, :aliases => '-x', :desc => 'Defines the name of the box or box image to build.'
85
85
  method_option :key_name, :aliases => '-k', :desc => 'Import a key pair.'
86
86
  method_option :key_path, :aliases => '-p', :desc => 'Public key data'
87
+ method_option :catalog, :aliases => '-y', :desc => 'A path for the yaml file data about the blueprint'
87
88
 
88
89
  def boot(blueprint, on, cloud_provider, as, name, test = false)
89
90
  Boot.boot(blueprint, cloud_provider, name,
@@ -91,7 +92,8 @@ class Forj < Thor
91
92
  options[:build_config], options[:branch],
92
93
  options[:git_repo], options[:boothook],
93
94
  options[:box_name], options[:key_name],
94
- options[:key_path], test)
95
+ options[:key_path],options[:region],
96
+ options[:catalog], test)
95
97
  end
96
98
 
97
99
  desc 'down', 'delete the Maestro box and all systems installed by the blueprint'
data/lib/boot.rb CHANGED
@@ -38,7 +38,7 @@ module Boot
38
38
  def boot(blueprint, cloud_provider, name,
39
39
  build, build_config_dir, build_config,
40
40
  branch, git_repo, boothook, box_name,
41
- key_name, key_path,
41
+ key_name, key_path, region, catalog,
42
42
  test = false)
43
43
  begin
44
44
  initial_msg = 'booting %s on %s' % [blueprint , cloud_provider]
@@ -48,33 +48,58 @@ module Boot
48
48
 
49
49
  forj_dir = File.expand_path(File.dirname(__FILE__))
50
50
  Dir.chdir(forj_dir)
51
- definitions = YamlParse.get_values('catalog.yaml')
51
+
52
+ if catalog
53
+ definitions = YamlParse.get_values(catalog)
54
+ else
55
+ definitions = YamlParse.get_values('catalog.yaml')
56
+ end
52
57
 
53
58
  maestro_url = definitions['default']['maestro']
54
59
 
55
60
  Repositories.clone_repo(maestro_url)
61
+ infra_exists = nil
62
+
63
+ begin
64
+ if File.directory?(definitions[blueprint]['infra'])
65
+ infra_exists = true
66
+ else
67
+ Repositories.create_infra
68
+ end
69
+ rescue => e
70
+ infra_exists = false
71
+ puts e.message
72
+ end
73
+
56
74
 
57
- network = Network.create_network(name)
58
- subnet = Network.create_subnet(network.id, name)
59
- router = Network.get_router(definitions[blueprint]['router'])
60
- Network.create_router_interface(subnet.id, router)
75
+ network = Network.get_or_create_network(definitions[blueprint]['network'])
76
+ begin
77
+ subnet = Network.get_or_create_subnet(network.id, name)
78
+ router = Network.get_router(definitions[blueprint]['router'])
79
+ Network.create_router_interface(subnet.id, router)
80
+ rescue => e
81
+ puts e.message
82
+ end
61
83
 
62
- security_group = SecurityGroup.create_security_group(blueprint)
84
+ security_group = SecurityGroup.get_or_create_security_group(definitions[blueprint]['security_group'])
63
85
 
64
- key_name = 'nova' unless key_name
65
- key_path = '~/.ssh/nova' unless key_path
86
+ key_name = definitions[blueprint]['keypair_name'] unless key_name
87
+ key_path = definitions[blueprint]['keypair_path'] unless key_path
66
88
  SecurityGroup.upload_existing_key(key_name, key_path)
67
89
 
68
- ports = definitions['redstone']['ports']
90
+ ports = definitions[blueprint]['ports']
69
91
 
70
92
  ports.each do|port|
71
- Network.create_security_group_rule(security_group.id, 'tcp', port, port)
93
+ Network.get_or_create_rule(security_group.id, 'tcp', port, port)
72
94
  end
73
95
 
74
96
  ENV['FORJ_HPC_NETID'] = network.id
75
97
  ENV['FORJ_SECURITY_GROUP'] = security_group.name
76
98
  ENV['FORJ_KEYPAIR'] = key_name
77
- ENV['FORJ_HPC_NOVA_KEYPUB'] = key_name
99
+ ENV['FORJ_HPC_KEYPUB'] = key_path
100
+ if region
101
+ ENV['FORJ_REGION'] = region
102
+ end
78
103
 
79
104
  # run build.sh to boot maestro
80
105
  current_dir = Dir.pwd
@@ -84,20 +109,23 @@ module Boot
84
109
 
85
110
  build = 'bin/build.sh' unless build
86
111
 
87
- build_config_dir = '~/.forj/maestro/build/conf' unless build_config_dir
88
-
89
- build_config = 'box' unless build_config
112
+ if infra_exists
113
+ build_config_dir = definitions[blueprint]['infra'] unless build_config_dir
114
+ else
115
+ build_config_dir = definitions[blueprint]['build_config_dir'] unless build_config_dir
116
+ end
90
117
 
91
- branch = 'master' unless branch
118
+ build_config = definitions[blueprint]['build_config'] unless build_config
92
119
 
93
- git_repo = 'review:forj-oss/maestro' unless git_repo
120
+ branch = definitions[blueprint]['branch'] unless branch
94
121
 
95
- box_name = 'maestro' unless box_name
122
+ box_name = definitions[blueprint]['box_name'] unless box_name
96
123
 
97
- boothook = '~/.forj/maestro/build/bin/build-tools/boothook.sh' unless boothook
124
+ meta = '--meta blueprint=%s --meta HPCLOUD_PRIV=~/.cache/forj/master.forj-13.5.g64' % [blueprint]
98
125
 
99
- command = '%s --build_ID %s --box-name %s --build-conf-dir %s --build-config %s --gitBranch %s --gitRepo %s --boothook %s' % [build, name, box_name, build_config_dir, build_config, branch, git_repo, boothook]
126
+ command = '%s --build_ID %s --box-name %s --build-conf-dir %s --build-config %s --gitBranch %s --debug-box %s' % [build, name, box_name, build_config_dir, build_config, branch, meta]
100
127
 
128
+ Logging.info('using build.sh for %s' % [name])
101
129
  Kernel.system(command)
102
130
  Dir.chdir(current_dir)
103
131
 
@@ -0,0 +1,293 @@
1
+ #!/bin/env python
2
+ #
3
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # This script is used to create a env file used by build.sh.
18
+ # It is based on Maestro/templates/infra/maestro.box.GITBRANCH.env.tmpl
19
+
20
+ # This script detects few tags, and ask to enter the appropriate vallue,
21
+ # then save the result to a directory given by the user.
22
+
23
+ # As this script is very early in the boot process, we are running on end user worstation.
24
+ # We will avoid adding non default module like:
25
+ # - ptemplates, django for template interpreter. We use our own simple code to make it work with basics rules.
26
+ # It provides variable detection, with comments and default variables.
27
+
28
+ import sys
29
+ import getopt
30
+ #import urllib2
31
+ #from urlparse import urlparse,ParseResult
32
+ import re
33
+ import logging
34
+ import logging.handlers
35
+ import yaml
36
+ import os
37
+ #import subprocess
38
+ #import distutils.spawn
39
+ #import string
40
+ #from datetime import date,datetime
41
+ #import time
42
+ #import tempfile
43
+ import readline
44
+
45
+ # Defining defaults
46
+
47
+ GITBRANCH='master'
48
+ MAESTRO_RPATH_TMPL="templates/infra/"
49
+ MAESTRO_TMPL_FILE="maestro.box.GITBRANCH.env.tmpl"
50
+ MAESTRO_TMPL_PROVIDER='hpcloud'
51
+
52
+ #
53
+ #
54
+
55
+ ##############################
56
+ def help(sMsg):
57
+ print 'build-env.py [-h|--help] --maestro-repo MaestroPath --env-path BuildEnvPath [--gitbranch BranchName] [-d|--debug] [-v|--verbose]'
58
+
59
+ # TODO Support for re-build it.
60
+
61
+ ##############################
62
+ # TODO: split this function in 3, for code readibility
63
+
64
+ def BuildEnv(EnvPath, MaestroFile, MaestroPath, GitBranch):
65
+ """Build env file if doesn't exist."""
66
+
67
+ global MAESTRO_TMPL_FILE
68
+ oLogging=logging.getLogger('build-env')
69
+
70
+ # -----------------------------------------------
71
+ # Check step ------------------------------------
72
+
73
+ if not os.path.exists(EnvPath):
74
+ oLogging.error("'%s' do not exist. This directory is required. (--env-path)", EnvPath)
75
+ sys.exit(1)
76
+
77
+ if not os.path.isdir(EnvPath):
78
+ oLogging.error("'%s' is not a valid directory (--env_path)", EnvPath)
79
+ sys.exit(1)
80
+
81
+ if not os.path.isdir(MaestroPath):
82
+ oLogging.error("'%s' is not a valid directory. Should refer to Maestro repository root dir.(--maestro-path)", MaestroPath)
83
+ sys.exit(1)
84
+
85
+
86
+ sInputFile=os.path.join(MaestroPath, MaestroFile)
87
+ if not os.path.exists(sInputFile):
88
+ oLogging.error("Unable to find template '%s' from '%s'. Are you sure about Maestro Repository root path given? Check and retry.", MaestroPath, MaestroFile)
89
+ sys.exit(1)
90
+
91
+ # Replace GITBRANCH Name by real git branch value.
92
+ sOutputFile=os.path.join(EnvPath,re.sub('GITBRANCH',GITBRANCH,MAESTRO_TMPL_FILE))
93
+ sOutputFile=re.sub('.tmpl$','',sOutputFile)
94
+
95
+ if os.path.exists(sOutputFile):
96
+ # TODO Support for re-build it.
97
+ oLogging.info("'%s' exists. If you want to rewrite it, remove the file before.", sOutputFile)
98
+ sys.exit(0)
99
+
100
+ # Load template variables and build list of variable to query
101
+ oLogging.debug("Opening template '%s'",sInputFile)
102
+ try:
103
+ fTmpl=open(sInputFile)
104
+ except IOError as e:
105
+ oLogging.error("Unable to open '%s'. Errno: %s (%s)", sInputFile, e.errno, e.strerror)
106
+ sys.exit(2)
107
+
108
+ # -----------------------------------------------
109
+ # Reading template ------------------------------
110
+
111
+ print("Reading template '{0}'".format(sInputFile))
112
+ oComments={}
113
+ oVars={}
114
+
115
+ # Search for Variable. If the variable name ends with '!', this value could not be null.
116
+ reVar=re.compile('[^$]{([A-Z_-]+)(!)?(:.*?)?}')
117
+ # 1: Variable Name
118
+ # 2: Required if = '!'
119
+ # 3: Default
120
+
121
+
122
+ # Search for comment
123
+ reComment=re.compile('^ *# +([A-Z_-]+): (.*)$')
124
+
125
+ for line in fTmpl:
126
+
127
+ # Detecting comment
128
+ oComment=reComment.search(line)
129
+ if oComment <> None:
130
+ oLogging.debug('Found "%s" = "%s"', oComment.group(1), oComment.group(2))
131
+ if oVars.has_key(oComment.group(1)):
132
+ oComments[oComment.group(1)]=oVars[oVar.group(1)]['comments']+'\n# '+oComment.group(2)
133
+ elif oComments.has_key(oComment.group(1)):
134
+ oComments[oComment.group(1)]=oComments[oComment.group(1)]+'\n# '+ oComment.group(2)
135
+ else:
136
+ oComments[oComment.group(1)]='# '+oComment.group(2)
137
+
138
+ oVar=reVar.search(line)
139
+ if oVar <> None:
140
+ oLogging.debug('Found var "%s" from "%s"',oVar.group(1),line)
141
+
142
+ sComment=''
143
+ if oComments.has_key(oVar.group(1)):
144
+ sComment=oComments[oVar.group(1)]
145
+ else:
146
+ oComments.remove(oVar.group(1))
147
+
148
+ sDefault=''
149
+ bRequired=False
150
+ if oVar.group(2) <> None :
151
+ bRequired=True
152
+ oLogging.debug("'%s' is required",oVar.group(1))
153
+ if oVar.group(3) <> None:
154
+ sDefault=oVar.group(3)[1:]
155
+ oLogging.debug("'%s' default value is '%s'",oVar.group(1),sDefault)
156
+
157
+
158
+ oVars[oVar.group(1)]={ 'comments': sComment,
159
+ 'required': bRequired,
160
+ 'default': sDefault }
161
+
162
+ oLogging.debug('template loaded.')
163
+
164
+ # -----------------------------------------------
165
+ # Ask section -----------------------------------
166
+
167
+ print "We need some information from you. Please ask the following question:\n"
168
+ # Time to ask information to the user.
169
+
170
+ for sElem in oVars:
171
+ print '{0}'.format(oVars[sElem]['comments'])
172
+ sPar="# "
173
+ if oVars[sElem]['default'] <> '':
174
+ sPar+='Default is "'+oVars[sElem]['default']+'".'
175
+ if oVars[sElem]['required'] :
176
+ if sPar <> "# " :
177
+ sPar+=' Required.'
178
+ else:
179
+ sPar='# Required.'
180
+
181
+ if sPar <> "":
182
+ print sPar
183
+ sValue=""
184
+
185
+ while sValue == "":
186
+ sValue=raw_input(sElem+'=')
187
+
188
+ if sValue == "":
189
+ sValue=oVars[sElem]['default']
190
+
191
+ if oVars[sElem]['required']:
192
+ if sValue == "":
193
+ print "Value required. Please enter a value."
194
+ else:
195
+ break
196
+
197
+ oVars[sElem]['value']=sValue
198
+ print '{0}="{1}"\n'.format(sElem,sValue)
199
+
200
+
201
+ fTmpl.seek(0) # Read the file again to replace data
202
+ try:
203
+ fOutputFile=open(sOutputFile,"w+")
204
+ except IOError as e:
205
+ oLogging.error("Unable to open '%s' for write. Errno: %s (%s)", sOutputFile, e.errno, e.strerror)
206
+ sys.exit(2)
207
+
208
+ print "--------------------------------\nThank you\nWriting '{0}'".format(sOutputFile)
209
+
210
+ # -----------------------------------------------
211
+ # Time to save the template. --------------------
212
+
213
+ reReplaced=re.compile('([^$])({([A-Z_-]+)(!)?(:.*?)?})')
214
+ for line in fTmpl:
215
+ oVar=reReplaced.search(line)
216
+
217
+ if oVar <> None:
218
+
219
+ if oVar.group(1) <> None:
220
+ sValue=oVar.group(1)+oVars[oVar.group(3)]['value']
221
+ else:
222
+ sValue=oVars[oVar.group(3)]['value']
223
+ sNewLine=reReplaced.sub(sValue,line)
224
+ else:
225
+ sNewLine=line
226
+
227
+ sys.stdout.flush()
228
+ fOutputFile.write(sNewLine)
229
+
230
+ fOutputFile.close()
231
+ fTmpl.close()
232
+ print 'Done'
233
+
234
+
235
+
236
+ ##############################
237
+ def main(argv):
238
+ """Main function"""
239
+
240
+ global GITBRANCH
241
+ global MAESTRO_TMPL_PROVIDER
242
+ global MAESTRO_RPATH_TMPL
243
+
244
+ oLogging=logging.getLogger('build-env')
245
+ oLogging.setLevel(20)
246
+
247
+ try:
248
+ opts,args = getopt.getopt(argv,"hp:vd:r:P:", ["help", "--for-provider=", "env-path=" , "maestro-path=" ,"debug" ,"verbose" ])
249
+ except getopt.GetoptError, e:
250
+ oLogging.error('Error: '+e.msg)
251
+ help()
252
+ sys.exit(2)
253
+
254
+ for opt, arg in opts:
255
+ if opt in ('-h', '--help'):
256
+ help()
257
+ sys.exit()
258
+ elif opt in ('-v','--verbose'):
259
+ if oLogging.level >20:
260
+ oLogging.setLevel(oLogging.level-10)
261
+ elif opt in ('--debug','-d'):
262
+ logging.getLogger().setLevel(logging.DEBUG)
263
+ logging.debug("Setting debug mode")
264
+ oLogging.setLevel(logging.DEBUG)
265
+ elif opt in ('-p', '--env-path'):
266
+ ENV_PATH=arg
267
+ elif opt in ('--gitbranch'):
268
+ GITBRANCH=arg
269
+ elif opt in ('-r','--maestro-path'):
270
+ MAESTRO_PATH=arg
271
+ elif opt in ('-P','--for-provider'):
272
+ TMPL_PROVIDER=arg
273
+
274
+ # Start Main tasks - Testing required variables.
275
+ if not 'ENV_PATH' in locals() or not 'MAESTRO_PATH' in locals():
276
+ oLogging.error("--env-path or --maestro-path values missing. Please check command flags.")
277
+ sys.exit(1)
278
+
279
+
280
+ global MAESTRO_TMPL_FILE # template file to use.
281
+
282
+ sMaestroFile=os.path.join(MAESTRO_RPATH_TMPL, MAESTRO_TMPL_PROVIDER+'-'+MAESTRO_TMPL_FILE)
283
+ BuildEnv(ENV_PATH, sMaestroFile, MAESTRO_PATH, GITBRANCH)
284
+
285
+ sys.exit(0)
286
+
287
+ #####################################
288
+ logging.basicConfig(format='%(asctime)s: %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
289
+
290
+ if __name__ == "__main__":
291
+ main(sys.argv[1:])
292
+
293
+
data/lib/catalog.yaml CHANGED
@@ -16,9 +16,18 @@ redstone:
16
16
  image: proto2b
17
17
  flavor: standard.xsmall
18
18
  ports: [22, 80, 443, 3131, 3000, 3132, 3133, 3134, 3135, 4505, 4506, 5000, 5666, 8000, 8080, 8081, 8083, 8125, 8139, 8140, 8773, 8774, 8776, 9292, 29418, 35357]
19
- keypair: nova
19
+ keypair_path: ~/.hpcloud/keypairs/nova
20
+ keypair_name: nova
20
21
  router: private-ext
21
- nodes: [maestro, ci, util, review]
22
+ security_group: default
23
+ network: private
24
+ # at this point you have to clone the infra project manually
25
+ build_config_dir: ~/forj/infra/build/boxes/maestro
26
+ build_config: box-13.5
27
+ branch: master
28
+ box_name: maestro
29
+ infra: ~/.forj/infra
30
+
22
31
 
23
32
  modus:
24
33
  ports: []
data/lib/compute.rb ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'rubygems'
19
+ require 'require_relative'
20
+
21
+ require_relative 'connection.rb'
22
+ include Connection
23
+ require_relative 'log.rb'
24
+ include Logging
25
+
26
+ #
27
+ # compute module
28
+ #
29
+ module Compute
30
+ def delete_forge(name)
31
+ instances = Connection.compute.servers.all(:name => name)
32
+ instances.each do|instance|
33
+ # make sure we don't delete another forge because fog filters
34
+ # the name in a "like syntax" way
35
+ Connection.compute.servers.get(instance.id).destroy
36
+ end
37
+ end
38
+ end
data/lib/down.rb CHANGED
@@ -24,6 +24,12 @@ require_relative 'yaml_parse.rb'
24
24
  include YamlParse
25
25
  require_relative 'security.rb'
26
26
  include SecurityGroup
27
+ require_relative 'log.rb'
28
+ include Logging
29
+ require_relative 'ssh.rb'
30
+ include Ssh
31
+ require_relative 'compute.rb'
32
+ include Compute
27
33
 
28
34
  #
29
35
  # Down module
@@ -32,30 +38,25 @@ module Down
32
38
  def down(name)
33
39
  begin
34
40
 
35
- puts 'deleting %s...' % [name]
41
+ initial_msg = 'deleting forge "%s"' % [name]
42
+ Logging.info(initial_msg)
43
+ puts (initial_msg)
36
44
 
37
- definitions = YamlParse::get_values('catalog.yaml')
45
+ Compute.delete_forge(name)
38
46
 
39
- # get the subnet
40
- subnet = Network::get_subnet(name)
41
-
42
- # delete the router interface
43
- router = Network::get_router(definitions['redstone']['router'])
47
+ router = Network.get_router('private-ext')
48
+ subnet = Network.get_subnet(name)
44
49
  Network.delete_router_interface(subnet.id, router)
45
50
 
46
- # delete subnet
47
51
  Network.delete_subnet(subnet.id)
48
-
49
- # delete security group
50
- # Network.delete_security_group(security_group.id)
51
-
52
- # delete network
53
- Network.delete_network(name)
52
+ network = Network.get_network(name)
53
+ Network.delete_network(network.name)
54
54
 
55
55
  rescue SystemExit, Interrupt
56
56
  puts 'process interrupted by user'
57
+ Logging.error('process interrupted by user')
57
58
  rescue Exception => e
58
- puts e
59
+ Logging.error(e.message)
59
60
  end
60
61
  end
61
62
  end
data/lib/network.rb CHANGED
@@ -27,6 +27,25 @@ include Logging
27
27
  # Network module
28
28
  #
29
29
  module Network
30
+ def get_or_create_network(name)
31
+ network = get_network(name)
32
+ if network == nil
33
+ network = create_network(name)
34
+ end
35
+ network
36
+ end
37
+
38
+ def get_network(name)
39
+ begin
40
+ info = 'getting network %s' % [name]
41
+ Logging.info(info)
42
+ Connection.network.networks.all(:name => name)[0]
43
+ rescue => e
44
+ puts e.message
45
+ Logging.error(e.message)
46
+ end
47
+ end
48
+
30
49
  def create_network(name)
31
50
  begin
32
51
  info = 'creating network %s' % [name]
@@ -39,13 +58,25 @@ module Network
39
58
 
40
59
  def delete_network(network_name)
41
60
  begin
42
- network = Connection.network.networks.all(:name => network_name)[0]
61
+ network = get_network(network_name)
43
62
  Connection.network.networks.get(network.id).destroy
44
63
  rescue => e
45
64
  Logging.error(e.message)
46
65
  end
47
66
  end
48
67
 
68
+ def get_or_create_subnet(network_id, name)
69
+ begin
70
+ subnet = get_subnet(name)
71
+ if subnet == nil
72
+ subnet = create_subnet(network_id, name)
73
+ end
74
+ subnet
75
+ rescue => e
76
+ Logging.error(e.message)
77
+ end
78
+ end
79
+
49
80
  def create_subnet(network_id, name)
50
81
  begin
51
82
  Connection.network.subnets.create(
data/lib/repositories.rb CHANGED
@@ -49,5 +49,23 @@ module Repositories
49
49
  Logging.error(e.message)
50
50
  end
51
51
  Dir.chdir(current_dir)
52
+ end
53
+ def create_infra
54
+ home = File.expand_path('~')
55
+ path = home + '/.forj/'
56
+ infra = path + 'infra/'
57
+
58
+ if File.directory?(infra)
59
+ FileUtils.rm_r(infra)
52
60
  end
61
+ Dir.mkdir(infra)
62
+
63
+ command = 'cp -rp ~/.forj/maestro/templates/infra/cloud-init ~/.forj/infra/'
64
+ Kernel.system(command)
65
+
66
+ Dir.chdir('build_tmpl')
67
+
68
+ fill_template = 'python build-env.py -p ~/.forj/infra --maestro-path ~/.forj/maestro'
69
+ Kernel.system(fill_template)
70
+ end
53
71
  end
data/lib/security.rb CHANGED
@@ -28,6 +28,15 @@ include Logging
28
28
  #
29
29
  module SecurityGroup
30
30
 
31
+ def get_or_create_security_group(name)
32
+ Logging.info('getting or creating security group for %s' % [name])
33
+ security_group = get_security_group(name)
34
+ if security_group == nil
35
+ security_group = create_security_group(name)
36
+ end
37
+ security_group
38
+ end
39
+
31
40
  def create_security_group(name)
32
41
  sec_group = nil
33
42
  begin
@@ -48,6 +57,14 @@ module SecurityGroup
48
57
  sec_group
49
58
  end
50
59
 
60
+ def get_security_group(name)
61
+ begin
62
+ Connection.network.security_groups.all({:name => name})[0]
63
+ rescue => e
64
+ Logging.error(e.message)
65
+ end
66
+ end
67
+
51
68
  def delete_security_group(security_group)
52
69
  begin
53
70
  sec_group = get_security_group(security_group)
@@ -82,14 +99,23 @@ module SecurityGroup
82
99
  end
83
100
  end
84
101
 
85
- def get_security_group(name)
102
+ def get_security_group_rule(port)
86
103
  begin
87
- Connection.network.security_groups.all({:name => name})
104
+ Connection.network.security_group_rules.all({:port_range_min => port, :port_range_max => port})[0]
88
105
  rescue => e
89
106
  Logging.error(e.message)
90
107
  end
91
108
  end
92
109
 
110
+ def get_or_create_rule(security_group_id, protocol, port_min, port_max)
111
+ Logging.info('getting or creating rule %s' % [port_min])
112
+ rule = get_security_group_rule(port_min)
113
+ if rule == nil
114
+ rule = create_security_group_rule(security_group_id, protocol, port_min, port_max)
115
+ end
116
+ rule
117
+ end
118
+
93
119
  def upload_existing_key(key_name, key_path)
94
120
  command = 'hpcloud keypairs:import %s %s' % [key_name, key_path]
95
121
  Kernel.system(command)
data/lib/setup.rb CHANGED
@@ -15,6 +15,12 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
+ require 'rubygems'
19
+ require 'require_relative'
20
+
21
+ require_relative 'yaml_parse.rb'
22
+ include YamlParse
23
+
18
24
  #
19
25
  # Setup module call the hpcloud functions
20
26
  #
@@ -22,6 +28,51 @@ module Setup
22
28
  def setup
23
29
  # delegate the initial configuration to hpcloud (unix_cli)
24
30
  Kernel.system('hpcloud account:setup')
25
- Kernel.system('hpcloud keypairs:add nova')
31
+ setup_credentials
32
+ save_cloud_fog
33
+ #Kernel.system('hpcloud keypairs:add nova')
26
34
  end
27
35
  end
36
+
37
+ def setup_credentials
38
+ puts 'Enter hpcloud username: '
39
+ hpcloud_os_user = $stdin.gets
40
+ puts 'Enter hpcloud password: '
41
+ hpcloud_os_key = $stdin.gets
42
+
43
+ home = File.expand_path('~')
44
+ creds = '%s/.cache/forj/creds' % [home]
45
+ File.open(creds, 'w') {|file|
46
+ file.write('HPCLOUD_OS_USER=%s' % [hpcloud_os_user])
47
+ file.write('HPCLOUD_OS_KEY=%s' % [hpcloud_os_key])
48
+ }
49
+ end
50
+
51
+
52
+ def save_cloud_fog
53
+ home = File.expand_path('~')
54
+
55
+ cloud_fog = '%s/.cache/forj/master.forj-13.5' % [home]
56
+ local_creds = '%s/.cache/forj/creds' % [home]
57
+
58
+ creds = '%s/.hpcloud/accounts/hp' % [home]
59
+ template = YAML.load_file(creds)
60
+ local_template = YAML.load_file(local_creds)
61
+
62
+
63
+ access_key = template[:credentials][:account_id]
64
+ secret_key = template[:credentials][:secret_key]
65
+
66
+ os_user = local_template['HPCLOUD_OS_USER']
67
+ os_key = local_template['HPCLOUD_OS_KEY']
68
+
69
+ File.open(cloud_fog, 'w') {|file|
70
+ file.write('HPCLOUD_OS_USER=%s' % [os_user])
71
+ file.write('HPCLOUD_OS_KEY=%s' % [os_key])
72
+ file.write('DNS_KEY=%s' % [access_key])
73
+ file.write('DNS_SECRET=%s' % [secret_key])
74
+ }
75
+
76
+ command = 'cat %s | gzip -c | base64 -w0 > %s.g64' % [cloud_fog, cloud_fog]
77
+ Kernel.system(command)
78
+ end
data/lib/ssh.rb CHANGED
@@ -18,11 +18,16 @@
18
18
  require 'rubygems'
19
19
  require 'require_relative'
20
20
 
21
+ require_relative 'log.rb'
22
+ include Logging
23
+
21
24
  #
22
25
  # ssh module
23
26
  #
24
27
  module Ssh
25
28
  def connect(name, server)
29
+ msg = 'logging into %s : %s' % [name, server]
30
+ Logging.info(msg)
26
31
  current_dir = Dir.pwd
27
32
  Dir.chdir(current_dir + '/lib')
28
33
 
data/lib/ssh.sh CHANGED
@@ -22,9 +22,10 @@ GRE="\e[92m"
22
22
  OW=`date +%Y-%m-%d.%H%M%S`
23
23
  logpath=~/.ssh/
24
24
  DB=~/hosts
25
- key_path=~/.ssh/
25
+ #key_path=~/.ssh/
26
+ #key_path=~/.hpcloud/keypairs/
26
27
  init_config=~/ssh_init
27
- key="nova"
28
+ key="nova.pem"
28
29
 
29
30
  if [ ! -f $DB ]; then
30
31
  cat > $DB <<'EOF'
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # Given that it is always loaded, you are encouraged to keep this file as
7
7
  # light-weight as possible. Requiring heavyweight dependencies from this file
8
- # will add to the boot time of your test suite on EVERY test run, even for an
8
+ # will add to the boot time of your test.rb suite on EVERY test.rb run, even for an
9
9
  # individual file that may not need all of that loaded. Instead, make a
10
10
  # separate helper file that requires this one and then use it only in the specs
11
11
  # that actually need it.
@@ -48,7 +48,7 @@ RSpec.configure do |config|
48
48
 
49
49
  # Seed global randomization in this process using the `--seed` CLI option.
50
50
  # Setting this allows you to use `--seed` to deterministically reproduce
51
- # test failures related to randomization by passing the same `--seed` value
51
+ # test.rb failures related to randomization by passing the same `--seed` value
52
52
  # as the one that triggered the failure.
53
53
  Kernel.srand config.seed
54
54
 
@@ -62,7 +62,7 @@ RSpec.configure do |config|
62
62
  expectations.syntax = :expect
63
63
  end
64
64
 
65
- # rspec-mocks config goes here. You can use an alternate test double
65
+ # rspec-mocks config goes here. You can use an alternate test.rb double
66
66
  # library (such as bogus or mocha) by changing the `mock_with` option here.
67
67
  config.mock_with :rspec do |mocks|
68
68
  # Enable only the newer, non-monkey-patching expect syntax.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forj
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.30
4
+ version: 0.0.31
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2014-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
16
- requirement: &14971980 !ruby/object:Gem::Requirement
16
+ requirement: &4634460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.16.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *14971980
24
+ version_requirements: *4634460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: nokogiri
27
- requirement: &14971040 !ruby/object:Gem::Requirement
27
+ requirement: &4633120 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.5.11
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *14971040
35
+ version_requirements: *4633120
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: fog
38
- requirement: &14969800 !ruby/object:Gem::Requirement
38
+ requirement: &4629760 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.19.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *14969800
46
+ version_requirements: *4629760
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: hpcloud
49
- requirement: &14966500 !ruby/object:Gem::Requirement
49
+ requirement: &4629180 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 2.0.8
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *14966500
57
+ version_requirements: *4629180
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: git
60
- requirement: &14965860 !ruby/object:Gem::Requirement
60
+ requirement: &4628460 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.2.7
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *14965860
68
+ version_requirements: *4628460
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rbx-require-relative
71
- requirement: &14965120 !ruby/object:Gem::Requirement
71
+ requirement: &4627320 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: 0.0.7
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *14965120
79
+ version_requirements: *4627320
80
80
  description: forj command line
81
81
  email:
82
82
  - forj@forj.io
@@ -86,6 +86,7 @@ extensions: []
86
86
  extra_rdoc_files: []
87
87
  files:
88
88
  - bin/forj
89
+ - lib/compute.rb
89
90
  - lib/connection.rb
90
91
  - lib/network.rb
91
92
  - lib/security.rb
@@ -99,6 +100,7 @@ files:
99
100
  - lib/ssh.sh
100
101
  - lib/log.rb
101
102
  - lib/helpers.rb
103
+ - lib/build_tmpl/build-env.py
102
104
  - spec/boot_spec.rb
103
105
  - spec/connection_spec.rb
104
106
  - spec/down_spec.rb