appscale-tools 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/LICENSE +37 -0
  2. data/README +17 -0
  3. data/bin/appscale-add-keypair +15 -0
  4. data/bin/appscale-describe-instances +16 -0
  5. data/bin/appscale-remove-app +13 -0
  6. data/bin/appscale-reset-pwd +13 -0
  7. data/bin/appscale-run-instances +15 -0
  8. data/bin/appscale-terminate-instances +14 -0
  9. data/bin/appscale-upload-app +13 -0
  10. data/doc/AdvancedNode.html +163 -0
  11. data/doc/AppControllerClient.html +831 -0
  12. data/doc/AppEngineConfigException.html +165 -0
  13. data/doc/AppScaleException.html +165 -0
  14. data/doc/AppScaleTools.html +768 -0
  15. data/doc/BadCommandLineArgException.html +166 -0
  16. data/doc/BadConfigurationException.html +166 -0
  17. data/doc/CommonFunctions.html +2559 -0
  18. data/doc/EncryptionHelper.html +332 -0
  19. data/doc/GodInterface.html +443 -0
  20. data/doc/InfrastructureException.html +166 -0
  21. data/doc/Node.html +470 -0
  22. data/doc/NodeLayout.html +1297 -0
  23. data/doc/Object.html +539 -0
  24. data/doc/ParseArgs.html +268 -0
  25. data/doc/RemoteLogging.html +268 -0
  26. data/doc/SimpleNode.html +163 -0
  27. data/doc/UsageText.html +1204 -0
  28. data/doc/UserAppClient.html +993 -0
  29. data/doc/VMTools.html +1365 -0
  30. data/doc/bin/appscale-add-keypair.html +56 -0
  31. data/doc/bin/appscale-describe-instances.html +56 -0
  32. data/doc/bin/appscale-remove-app.html +56 -0
  33. data/doc/bin/appscale-reset-pwd.html +56 -0
  34. data/doc/bin/appscale-run-instances.html +56 -0
  35. data/doc/bin/appscale-terminate-instances.html +56 -0
  36. data/doc/bin/appscale-upload-app.html +56 -0
  37. data/doc/created.rid +21 -0
  38. data/doc/images/add.png +0 -0
  39. data/doc/images/brick.png +0 -0
  40. data/doc/images/brick_link.png +0 -0
  41. data/doc/images/bug.png +0 -0
  42. data/doc/images/bullet_black.png +0 -0
  43. data/doc/images/bullet_toggle_minus.png +0 -0
  44. data/doc/images/bullet_toggle_plus.png +0 -0
  45. data/doc/images/date.png +0 -0
  46. data/doc/images/delete.png +0 -0
  47. data/doc/images/find.png +0 -0
  48. data/doc/images/loadingAnimation.gif +0 -0
  49. data/doc/images/macFFBgHack.png +0 -0
  50. data/doc/images/package.png +0 -0
  51. data/doc/images/page_green.png +0 -0
  52. data/doc/images/page_white_text.png +0 -0
  53. data/doc/images/page_white_width.png +0 -0
  54. data/doc/images/plugin.png +0 -0
  55. data/doc/images/ruby.png +0 -0
  56. data/doc/images/tag_blue.png +0 -0
  57. data/doc/images/tag_green.png +0 -0
  58. data/doc/images/transparent.png +0 -0
  59. data/doc/images/wrench.png +0 -0
  60. data/doc/images/wrench_orange.png +0 -0
  61. data/doc/images/zoom.png +0 -0
  62. data/doc/index.html +116 -0
  63. data/doc/js/darkfish.js +153 -0
  64. data/doc/js/jquery.js +18 -0
  65. data/doc/js/navigation.js +142 -0
  66. data/doc/js/quicksearch.js +114 -0
  67. data/doc/js/search.js +94 -0
  68. data/doc/js/search_index.js +1 -0
  69. data/doc/js/searcher.js +228 -0
  70. data/doc/js/thickbox-compressed.js +10 -0
  71. data/doc/lib/app_controller_client_rb.html +60 -0
  72. data/doc/lib/appscale_tools_rb.html +88 -0
  73. data/doc/lib/common_functions_rb.html +78 -0
  74. data/doc/lib/custom_exceptions_rb.html +54 -0
  75. data/doc/lib/encryption_helper_rb.html +60 -0
  76. data/doc/lib/godinterface_rb.html +52 -0
  77. data/doc/lib/node_layout_rb.html +55 -0
  78. data/doc/lib/parse_args_rb.html +58 -0
  79. data/doc/lib/remote_log_rb.html +58 -0
  80. data/doc/lib/sshcopyid.html +174 -0
  81. data/doc/lib/usage_text_rb.html +58 -0
  82. data/doc/lib/user_app_client_rb.html +62 -0
  83. data/doc/lib/vm_tools_rb.html +62 -0
  84. data/doc/table_of_contents.html +496 -0
  85. data/lib/app_controller_client.rb +181 -0
  86. data/lib/appscale_tools.rb +403 -0
  87. data/lib/common_functions.rb +1467 -0
  88. data/lib/custom_exceptions.rb +25 -0
  89. data/lib/encryption_helper.rb +86 -0
  90. data/lib/godinterface.rb +152 -0
  91. data/lib/node_layout.rb +665 -0
  92. data/lib/parse_args.rb +415 -0
  93. data/lib/remote_log.rb +46 -0
  94. data/lib/sshcopyid +65 -0
  95. data/lib/usage_text.rb +144 -0
  96. data/lib/user_app_client.rb +245 -0
  97. data/lib/vm_tools.rb +549 -0
  98. data/test/tc_app_controller_client.rb +10 -0
  99. data/test/tc_appscale_add_keypair.rb +44 -0
  100. data/test/tc_appscale_describe_instances.rb +69 -0
  101. data/test/tc_appscale_remove_app.rb +128 -0
  102. data/test/tc_appscale_reset_pwd.rb +156 -0
  103. data/test/tc_appscale_run_instances.rb +48 -0
  104. data/test/tc_appscale_terminate_instances.rb +104 -0
  105. data/test/tc_appscale_upload_app.rb +166 -0
  106. data/test/tc_common_functions.rb +56 -0
  107. data/test/tc_encryption_helper.rb +10 -0
  108. data/test/tc_god_interface.rb +10 -0
  109. data/test/tc_node_layout.rb +93 -0
  110. data/test/tc_parse_args.rb +160 -0
  111. data/test/tc_user_app_client.rb +10 -0
  112. data/test/tc_vm_tools.rb +10 -0
  113. data/test/ts_all.rb +20 -0
  114. metadata +211 -0
data/lib/sshcopyid ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env expect
2
+
3
+ #############################
4
+ #
5
+ # Author : Kowshik Prakasam
6
+ #
7
+ # An expect script to automatically login to each host as a particular user and
8
+ # install the user's public key using ssh-copy-id
9
+ #
10
+ # If successful, exits with zero (0) status
11
+ # If unsuccessful, exits with non-zero status
12
+ #
13
+ # Usage : sshcopy.exp <user@host> <key_file> <password>
14
+ # Example : sshcopy.exp root@128.111.55.234 /home/appscale/.appscale/appscale joe
15
+ #
16
+ #############################
17
+
18
+ # Procedure to interact with ssh-copy-id command
19
+ # Parameter : password
20
+ proc sshcopyid { password } {
21
+ expect {
22
+ # Send password at 'Password' prompt and tell expect to continue(i.e. exp_continue)
23
+ -re "\[P|p]assword:" { exp_send "$password\r"
24
+ exp_continue }
25
+
26
+ #Returning 1 as ssh-copy-id has failed
27
+ -re "^\[P|p]ermission denied*" { return 1}
28
+
29
+ #Answering yes to ssh host
30
+ -nocase "are you sure you want to continue connecting (yes/no)?" { exp_send "yes\r"
31
+ exp_continue }
32
+
33
+ # Tell expect stay in this 'expect' block and for each character that ssh-copy-id prints while doing the copy
34
+ # Reset the timeout counter back to 0
35
+ -re . { exp_continue }
36
+ timeout { return 1 }
37
+
38
+ #Returning 0 as ssh-copy-id was successful
39
+ eof { return 0 }
40
+ }
41
+ }
42
+
43
+ #Parsing command-line arguments
44
+ set host [lrange $argv 0 0]
45
+ set key_file [lrange $argv 1 1]
46
+ set password [lrange $argv 2 2]
47
+
48
+ #Setting timeout to an arbitrary value of 3 that works well for ssh-copy-id
49
+ set timeout 3
50
+
51
+ # Execute ssh-copy-id command
52
+ eval spawn ssh-copy-id -i $key_file $host
53
+
54
+ #Get the result of ssh-copy-id
55
+ set sshcopyid_result [sshcopyid $password]
56
+
57
+ # If ssh-copy-id was successful
58
+ if { $sshcopyid_result == 0 } {
59
+ #Exit with zero status
60
+ exit 0
61
+ }
62
+
63
+ # Error attempting ssh-copy-id, so exit with non-zero status
64
+ exit 1
65
+
data/lib/usage_text.rb ADDED
@@ -0,0 +1,144 @@
1
+ # Programmer: Chris Bunch
2
+
3
+ require 'common_functions'
4
+ require 'custom_exceptions'
5
+
6
+ module UsageText
7
+ def self.get_usage(file_name, flags)
8
+ preamble = "#{AS_VERSION}\n\nUsage: #{file_name} OPTIONS\n\nFlags:"
9
+ flag_text = ""
10
+ flags.each { |flag|
11
+ if !self.respond_to?(flag.to_sym)
12
+ raise BadCommandLineArgException.new(flag)
13
+ end
14
+
15
+ flag_text += "\n\t" + self.send(flag.to_sym)
16
+ }
17
+ return preamble + flag_text + "\n\n"
18
+ end
19
+
20
+ def self.appengine
21
+ "--appengine NUM: The number of application servers that should be spawned up for each Google App Engine app."
22
+ end
23
+
24
+ def self.appname
25
+ "--appname APPNAME: The name of the application to remove."
26
+ end
27
+
28
+ def self.auto
29
+ "--auto: Requests the SSH login password from the user once, and then automatically reuses the password on each machine."
30
+ end
31
+
32
+ def self.backup_neptune_info
33
+ "--backup_neptune_info FILE: Backs up Neptune job metadata to FILE."
34
+ end
35
+
36
+ def self.confirm
37
+ "--confirm: Skips the confirmation step when removing an application."
38
+ end
39
+
40
+ def self.email
41
+ "--email EMAIL: Uses EMAIL as the app administrator for the given application instead of prompting for it."
42
+ end
43
+
44
+ def self.file
45
+ "--file FILE: The app to upload. Must be a directory or file tar'ed up via 'tar -czf app.tar.gz .' in the application's top level directory."
46
+ end
47
+
48
+ def self.force
49
+ "--force: If the given keyname is already in use, remove it from the system and add a new key with the same name."
50
+ end
51
+
52
+ def self.group
53
+ "--group: The name of the security group to create when running over a cloud infrastructure."
54
+ end
55
+
56
+ def self.h
57
+ "-h: Displays this usage message."
58
+ end
59
+
60
+ def self.help
61
+ "--help: Displays this usage message."
62
+ end
63
+
64
+ def self.instance_type
65
+ "--instance_type: The instance type to use if using Eucalyptus. Defaults to m1.large if not provided. Supported values are m1.large, m1.xlarge, and c1.xlarge."
66
+ end
67
+
68
+ def self.iaas
69
+ "--iaas INFRASTRUCTURE: Same as --infrastructure, but if no value is provided, defaults to euca."
70
+ end
71
+
72
+ def self.infrastructure
73
+ "--infrastructure INFRASTRUCTURE: The cloud infrastructure that AppScale should utilize. Acceptable values are: #{VALID_CLOUD_TYPES.join(', ')}."
74
+ end
75
+
76
+ def self.ips
77
+ "--ips: The YAML file containing the IPs (and optionally, the service placement) of the machines to use."
78
+ end
79
+
80
+ def self.keyname
81
+ "--keyname KEYNAME: The name of the SSH key to use for Eucalyptus. Two AppScale instances can be run concurrently in one cloud if they have unique names, and they can conflict if they have the same name."
82
+ end
83
+
84
+ def self.machine
85
+ "--machine IMAGE_ID: The machine image to use in Amazon EC2 or Eucalyptus. Supercedes the contents of the environment variable APPSCALE_MACHINE, which is otherwise used if this flag is not present."
86
+ end
87
+
88
+ def self.min
89
+ "--min NUM: The minimum number of VMs to spawn for AppScale in cloud deployments."
90
+ end
91
+
92
+ def self.max
93
+ "--max NUM: The maximum number of VMs to spawn for AppScale in cloud deployments."
94
+ end
95
+
96
+ def self.n
97
+ "-n NUM: The replication factor that should be used with the underlying database."
98
+ end
99
+
100
+ def self.r
101
+ "-r NUM: The number of database nodes needed for a read to succeed. Not supported by all databases."
102
+ end
103
+
104
+ def self.restore_from_tar
105
+ "--restore_from_tar LOCATION: The location of the tar file that can be used to back up the state of a previously running AppScale deployment."
106
+ end
107
+
108
+ def self.restore_neptune_info
109
+ "--restore_neptune_info LOCATION: The location of a previously saved Neptune job metadata file, to be used when starting a new Appscale deployment."
110
+ end
111
+
112
+ def self.scp
113
+ "--scp LOCATION: A location on the local file system where a copy of the AppScale main branch is located. This flag instructs the tools to rsync this branch over to all nodes used. Useful for testing and debugging. If no value is provided, ~/appscale is used."
114
+ end
115
+
116
+ def self.table
117
+ "--table DATABASE: The database to use with AppScale. Acceptable values are: #{VALID_TABLE_TYPES.join(', ')} (default is #{DEFAULT_DATASTORE})."
118
+ end
119
+
120
+ def self.test
121
+ "--test: Uses a default username and password when uploading an application. Intended for testing only."
122
+ end
123
+
124
+ def self.usage
125
+ "--usage: Displays this usage message."
126
+ end
127
+
128
+ def self.v
129
+ "-v: Displays extra output. Useful for debugging."
130
+ end
131
+
132
+ def self.verbose
133
+ "--verbose: Displays extra output. Useful for debugging."
134
+ end
135
+
136
+ def self.version
137
+ "--version: Displays the version of the AppScale tools used."
138
+ end
139
+
140
+ def self.w
141
+ "-w NUM: The number of database nodes needed for a write to succeed. Not supported by all databases."
142
+ end
143
+
144
+ end
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/ruby -w
2
+ # Programmer: Chris Bunch
3
+
4
+ require 'base64'
5
+ require 'openssl'
6
+ require 'soap/rpc/driver'
7
+ require 'timeout'
8
+
9
+ ADMIN_CAPABILITIES = ["upload_app", "mr_api", "ec2_api", "neptune_api"].join(":")
10
+
11
+ class UserAppClient
12
+ attr_reader :conn, :ip, :secret
13
+
14
+ def initialize(ip, secret)
15
+ @ip = ip
16
+ @secret = secret
17
+
18
+ @conn = SOAP::RPC::Driver.new("https://#{@ip}:4343")
19
+ @conn.add_method("change_password", "user", "password", "secret")
20
+ @conn.add_method("commit_new_user", "user", "passwd", "utype", "secret")
21
+ @conn.add_method("commit_new_app", "user", "appname", "language", "secret")
22
+ @conn.add_method("commit_tar", "app_name", "tar", "secret")
23
+ @conn.add_method("delete_app", "appname", "secret")
24
+ @conn.add_method("is_app_enabled", "appname", "secret")
25
+ @conn.add_method("does_user_exist", "username", "secret")
26
+ @conn.add_method("get_app_data", "appname", "secret")
27
+ @conn.add_method("delete_instance", "appname", "host", "port", "secret")
28
+ @conn.add_method("get_tar", "app_name", "secret")
29
+ @conn.add_method("add_instance", "appname", "host", "port", "secret")
30
+ @conn.add_method("set_cloud_admin_status", "username", "is_cloud_admin", "secret")
31
+ @conn.add_method("set_capabilities", "username", "capabilities", "secret")
32
+ end
33
+
34
+ def make_call(timeout, retry_on_except)
35
+ result = ""
36
+ begin
37
+ Timeout::timeout(timeout) do
38
+ begin
39
+ yield if block_given?
40
+ end
41
+ end
42
+ rescue OpenSSL::SSL::SSLError
43
+ retry
44
+ rescue Errno::ECONNREFUSED
45
+ if retry_on_except
46
+ sleep(1)
47
+ retry
48
+ else
49
+ abort("We were unable to establish a connection with the UserAppServer at the designated location. Is AppScale currently running?")
50
+ end
51
+ rescue Exception => except
52
+ if except.class == Interrupt
53
+ abort
54
+ end
55
+
56
+ puts "An exception of type #{except.class} was thrown."
57
+ retry if retry_on_except
58
+ end
59
+ end
60
+
61
+ def commit_new_user(user, encrypted_password, user_type="xmpp_user", retry_on_except=true)
62
+ result = ""
63
+ make_call(10, retry_on_except) {
64
+ result = @conn.commit_new_user(user, encrypted_password, user_type, @secret)
65
+ }
66
+
67
+ if result == "true"
68
+ puts "\nYour user account has been created successfully."
69
+ elsif result == "false"
70
+ abort("\nWe were unable to create your user account. Please contact your cloud administrator for further details.")
71
+ else
72
+ puts "\n[unexpected] Commit new user returned: [#{result}]"
73
+ end
74
+ end
75
+
76
+ def commit_new_app(user, app_name, language, file_location)
77
+ commit_new_app_name(user, app_name, language)
78
+ commit_tar(app_name, file_location)
79
+ end
80
+
81
+ def commit_new_app_name(user, app_name, language, retry_on_except=true)
82
+ result = ""
83
+ make_call(10, retry_on_except) {
84
+ result = @conn.commit_new_app(user, app_name, language, @secret)
85
+ }
86
+
87
+ if result == "true"
88
+ puts "We have reserved the name #{app_name} for your application."
89
+ elsif result == "Error: appname already exist"
90
+ puts "We are uploading a new version of the application #{app_name}."
91
+ elsif result == "Error: User not found"
92
+ abort("We were unable to reserve the name of your application. Please contact your cloud administrator for more information.")
93
+ else
94
+ puts "[unexpected] Commit new app says: [#{result}]"
95
+ end
96
+ end
97
+
98
+ def commit_tar(app_name, file_location, retry_on_except=true)
99
+ result = ""
100
+ make_call(10, retry_on_except) {
101
+ result = @conn.commit_tar(app_name, file_location, @secret)
102
+
103
+ if result == "true"
104
+ puts "#{app_name} was uploaded successfully."
105
+ elsif result == "Error: app does not exist"
106
+ abort("We were unable to upload your application. Please contact your cloud administrator for more information.")
107
+ else
108
+ puts "[unexpected] Commit new tar says: [#{result}]"
109
+ retry
110
+ end
111
+ }
112
+ end
113
+
114
+ def change_password(user, new_password, retry_on_except=true)
115
+ result = ""
116
+ make_call(10, retry_on_except) {
117
+ result = @conn.change_password(user, new_password, @secret)
118
+ }
119
+
120
+ if result == "true"
121
+ puts "We successfully changed the password for the given user."
122
+ elsif result == "Error: user not found"
123
+ puts "We were unable to locate a user with the given username."
124
+ else
125
+ puts "[unexpected] Got this message back: [#{result}]"
126
+ end
127
+ end
128
+
129
+ def delete_app(app, retry_on_except=true)
130
+ result = ""
131
+ make_call(10, retry_on_except) {
132
+ result = @conn.delete_app(app, @secret)
133
+ }
134
+
135
+ if result == "true"
136
+ return true
137
+ else
138
+ return result
139
+ end
140
+ end
141
+
142
+ def does_app_exist?(app, retry_on_except=true)
143
+ result = ""
144
+ make_call(10, retry_on_except) {
145
+ result = @conn.get_app_data(app, @secret)
146
+ }
147
+
148
+ begin
149
+ num_hosts = Integer(result.scan(/num_ports:(\d+)/).flatten.to_s)
150
+ rescue Exception
151
+ num_hosts = 0
152
+ end
153
+
154
+ if num_hosts > 0
155
+ return true
156
+ else
157
+ return false
158
+ end
159
+ end
160
+
161
+ def does_user_exist?(user, retry_on_except=true)
162
+ result = ""
163
+ make_call(10, retry_on_except) {
164
+ result = @conn.does_user_exist(user, @secret)
165
+ }
166
+
167
+ if result == "true"
168
+ return true
169
+ else
170
+ return false
171
+ end
172
+ end
173
+
174
+ def get_app_data(appname, retry_on_except=true)
175
+ result = ""
176
+ make_call(10, retry_on_except) {
177
+ result = @conn.get_app_data(appname, @secret)
178
+ }
179
+
180
+ return result
181
+ end
182
+
183
+ def get_app_admin(appname, retry_on_except=true)
184
+ app_data = get_app_data(appname, retry_on_except)
185
+ return app_data.scan(/app_owner:(.*)/).flatten.to_s
186
+ end
187
+
188
+ def delete_instance(appname, host, port, retry_on_except=true)
189
+ result = ""
190
+ make_call(10, retry_on_except) {
191
+ result = @conn.delete_instance(appname, host, port, @secret)
192
+ }
193
+
194
+ return result
195
+ end
196
+
197
+ def get_all_apps(retry_on_except=true)
198
+ result = ""
199
+ make_call(10, retry_on_except) {
200
+ result = @conn.get_all_apps(@secret)
201
+ }
202
+
203
+ return result
204
+ end
205
+
206
+ def get_tar(appname, retry_on_except=true)
207
+ result = ""
208
+ make_call(300, retry_on_except) {
209
+ result = @conn.get_tar(appname, @secret)
210
+ }
211
+
212
+ return result
213
+ end
214
+
215
+ def add_instance(appname, host, port, retry_on_except=true)
216
+ result = ""
217
+ make_call(10, retry_on_except) {
218
+ result = @conn.add_instance(appname, host, port, @secret)
219
+ }
220
+
221
+ return result
222
+ end
223
+
224
+ def set_cloud_admin_status(username, new_status)
225
+ result = ""
226
+ make_call(NO_TIMEOUT, RETRY_ON_FAIL) {
227
+ result = @conn.set_cloud_admin_status(username, new_status, @secret)
228
+ }
229
+
230
+ return result
231
+ end
232
+
233
+ def set_capabilities(username, capabilities)
234
+ result = ""
235
+ make_call(NO_TIMEOUT, RETRY_ON_FAIL) {
236
+ result = @conn.set_capabilities(username, capabilities, @secret)
237
+ }
238
+
239
+ return result
240
+ end
241
+
242
+ def set_cloud_admin_capabilities(username)
243
+ return set_capabilities(username, ADMIN_CAPABILITIES)
244
+ end
245
+ end