Fix the merge conflicts

This commit is contained in:
Kelven Yang 2013-02-01 15:22:58 -08:00
commit e74f72be34
9 changed files with 443 additions and 293 deletions

View File

@ -80,9 +80,12 @@
<bean id="NiciraNvp" class="com.cloud.network.element.NiciraNvpElement">
<property name="name" value="NiciraNvp"/>
</bean>
<!--
<bean id="BigSwitchVnsElementService" class="com.cloud.network.element.BigSwitchVnsElement">
<property name="name" value="BigSwitchVnsElementService"/>
</bean>
-->
<!--
Adapters
@ -238,10 +241,12 @@
<bean id="NiciraNvpGuestNetworkGuru" class="com.cloud.network.guru.NiciraNvpGuestNetworkGuru">
<property name="name" value="NiciraNvpGuestNetworkGuru"/>
</bean>
<!--
<bean id="BigSwitchVnsGuestNetworkGuru" class=".BigSwitchVnsGuestNetworkGuru">
<property name="name" value="com.cloud.network.guru.BigSwitchVnsGuestNetworkGuru"/>
</bean>
-->
<!--
Hypervisor Gurus

View File

@ -16,6 +16,6 @@
# under the License.
try:
from common import __version__
from config import __version__
except ImportError, e:
print e

View File

@ -1,97 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
try:
import re
from marvin.cloudstackAPI import *
from marvin import cloudstackAPI
except ImportError, e:
import sys
print "ImportError", e
sys.exit(1)
completions = cloudstackAPI.__all__
def get_api_module(api_name, api_class_strs=[]):
try:
api_mod = __import__("marvin.cloudstackAPI.%s" % api_name,
globals(), locals(), api_class_strs, -1)
except ImportError, e:
print "Error: API not found", e
return None
return api_mod
def main():
"""
cachegen.py creates a precached dictionary for all the available verbs in
the predefined grammar of cloudmonkey, it dumps the dictionary in an
importable python module. This way we cheat on the runtime overhead of
completing commands and help docs. This reduces the overall search and
cache_miss (computation) complexity from O(n) to O(1) for any valid cmd.
"""
pattern = re.compile("[A-Z]")
verbs = list(set([x[:pattern.search(x).start()] for x in completions
if pattern.search(x) is not None]).difference(['cloudstack']))
# datastructure {'verb': {cmd': ['api', [params], doc, required=[]]}}
cache_verbs = {}
for verb in verbs:
completions_found = filter(lambda x: x.startswith(verb), completions)
cache_verbs[verb] = {}
for api_name in completions_found:
api_cmd_str = "%sCmd" % api_name
api_mod = get_api_module(api_name, [api_cmd_str])
if api_mod is None:
continue
try:
api_cmd = getattr(api_mod, api_cmd_str)()
required = api_cmd.required
doc = api_mod.__doc__
except AttributeError, e:
print "Error: API attribute %s not found!" % e
params = filter(lambda x: '__' not in x and 'required' not in x,
dir(api_cmd))
if len(required) > 0:
doc += "\nRequired args: %s" % " ".join(required)
doc += "\nArgs: %s" % " ".join(params)
api_name_lower = api_name.replace(verb, '').lower()
cache_verbs[verb][api_name_lower] = [api_name, params, doc,
required]
f = open("precache.py", "w")
f.write("""# Auto-generated code by cachegen.py
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.""")
f.write("\nprecached_verbs = %s" % cache_verbs)
f.close()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
try:
import json
import os
import re
from requester import monkeyrequest
except ImportError, e:
import sys
print "ImportError", e
sys.exit(1)
def getvalue(dictionary, key):
if key in dictionary:
return dictionary[key]
else:
return None
def csv_str_as_list(string):
if string is not None:
return filter(lambda x: x.strip() != '', string.split(','))
else:
return []
def cachegen_from_file(json_file):
f = open(json_file, 'r')
data = f.read()
f.close()
try:
apis = json.loads(data)
except ValueError, e:
print "Error processing json in cachegen()", e
return cachegen(apis)
def cachegen(apis):
pattern = re.compile("[A-Z]")
responsekey = filter(lambda x: 'response' in x, apis.keys())
if len(responsekey) == 0:
print "[cachegen] Invalid dictionary, has no response"
return None
if len(responsekey) != 1:
print "[cachegen] Multiple responsekeys, chosing first one"
responsekey = responsekey[0]
verbs = set()
cache = {}
cache['count'] = getvalue(apis[responsekey], 'count')
for api in getvalue(apis[responsekey], 'api'):
name = getvalue(api, 'name')
response = getvalue(api, 'response')
idx = pattern.search(name).start()
verb = name[:idx]
subject = name[idx:]
apidict = {}
apidict['name'] = name
apidict['description'] = getvalue(api, 'description')
apidict['isasync'] = getvalue(api, 'isasync')
apidict['related'] = csv_str_as_list(getvalue(api, 'related'))
required = []
apiparams = []
for param in getvalue(api, 'params'):
apiparam = {}
apiparam['name'] = getvalue(param, 'name')
apiparam['description'] = getvalue(param, 'description')
apiparam['required'] = (getvalue(param, 'required') is True)
apiparam['length'] = int(getvalue(param, 'length'))
apiparam['type'] = getvalue(param, 'type')
apiparam['related'] = csv_str_as_list(getvalue(param, 'related'))
if apiparam['required']:
required.append(apiparam['name'])
apiparams.append(apiparam)
apidict['requiredparams'] = required
apidict['params'] = apiparams
apidict['response'] = getvalue(api, 'response')
cache[verb] = {subject: apidict}
verbs.add(verb)
cache['verbs'] = list(verbs)
return cache
def main(json_file):
"""
cachegen.py creates a precache datastore of all available apis of
CloudStack and dumps the precache dictionary in an
importable python module. This way we cheat on the runtime overhead of
completing commands and help docs. This reduces the overall search and
cache_miss (computation) complexity from O(n) to O(1) for any valid cmd.
"""
f = open("precache.py", "w")
f.write("""# -*- coding: utf-8 -*-
# Auto-generated code by cachegen.py
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.""")
f.write("\nprecache = %s" % cachegen_from_file(json_file))
f.close()
if __name__ == "__main__":
json_file = 'listapis.json'
if os.path.exists(json_file):
main(json_file)
else:
pass
#print "[ERROR] cli:cachegen is unable to locate %s" % json_file

View File

@ -20,7 +20,6 @@
try:
import atexit
import cmd
import codecs
import json
import logging
import os
@ -28,18 +27,16 @@ try:
import re
import shlex
import sys
import time
import types
from ConfigParser import ConfigParser, SafeConfigParser
from urllib2 import HTTPError, URLError
from httplib import BadStatusLine
from prettytable import PrettyTable
from common import __version__, config_dir, config_file, config_fields
from common import precached_verbs
from lexer import monkeyprint
from config import __version__, config_file
from config import precached_verbs, read_config, write_config
from printer import monkeyprint
from requester import monkeyrequest
from prettytable import PrettyTable
from marvin.cloudstackConnection import cloudConnection
from marvin.cloudstackException import cloudstackAPIException
from marvin.cloudstackAPI import *
@ -70,8 +67,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
intro = ("☁ Apache CloudStack 🐵 cloudmonkey " + __version__ +
". Type help or ? to list commands.\n")
ruler = "="
config_dir = config_dir
config_file = config_file
apicache = {}
# datastructure {'verb': {cmd': ['api', [params], doc, required=[]]}}
cache_verbs = precached_verbs
config_options = []
@ -79,31 +75,8 @@ class CloudMonkeyShell(cmd.Cmd, object):
def __init__(self, pname, verbs):
self.program_name = pname
self.verbs = verbs
global config_fields
first_time = False
if not os.path.exists(self.config_dir):
os.makedirs(self.config_dir)
if os.path.exists(self.config_file):
config = self.read_config()
else:
first_time = True
config = self.write_config(first_time)
for section in config_fields.keys():
for key in config_fields[section].keys():
try:
self.config_options.append(key)
setattr(self, key, config.get(section, key))
except Exception:
print "Please fix `%s` in %s" % (key, self.config_file)
sys.exit()
if first_time:
print "Welcome! Using `set` configure the necessary settings:"
print " ".join(sorted(self.config_options))
print "Config file:", self.config_file
print "For debugging, tail -f", self.log_file, "\n"
self.config_options = read_config(self.get_attr, self.set_attr)
self.prompt = self.prompt.strip() + " " # Cosmetic fix for prompt
logging.basicConfig(filename=self.log_file,
@ -111,40 +84,20 @@ class CloudMonkeyShell(cmd.Cmd, object):
logger.debug("Loaded config fields:\n%s" % map(lambda x: "%s=%s" %
(x, getattr(self, x)),
self.config_options))
cmd.Cmd.__init__(self)
if not os.path.exists(self.config_file):
config = self.write_config()
try:
if os.path.exists(self.history_file):
readline.read_history_file(self.history_file)
atexit.register(readline.write_history_file, self.history_file)
except IOError:
print("Error: history support")
monkeyprint("Error: history support")
def read_config(self):
config = ConfigParser()
try:
with open(self.config_file, 'r') as cfg:
config.readfp(cfg)
except IOError, e:
self.print_shell("Error: config_file not found", e)
return config
def get_attr(self, field):
return getattr(self, field)
def write_config(self, first_time=False):
global config_fields
config = ConfigParser()
for section in config_fields.keys():
config.add_section(section)
for key in config_fields[section].keys():
if first_time:
config.set(section, key, config_fields[section][key])
else:
config.set(section, key, getattr(self, key))
with open(self.config_file, 'w') as cfg:
config.write(cfg)
return config
def set_attr(self, field, value):
return setattr(self, field, value)
def emptyline(self):
pass
@ -158,20 +111,8 @@ class CloudMonkeyShell(cmd.Cmd, object):
except KeyboardInterrupt:
print("^C")
def print_shell(self, *args):
output = ""
try:
for arg in args:
arg = str(arg)
if isinstance(type(args), types.NoneType):
continue
output += arg
if self.color == 'true':
monkeyprint(output)
else:
print output
except Exception, e:
self.print_shell("Error: " + e)
def monkeyprint(self, *args):
monkeyprint((self.color == 'true'), *args)
def print_result(self, result, result_filter=None):
if result is None or len(result) == 0:
@ -179,7 +120,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
def printer_helper(printer, toprow):
if printer:
self.print_shell(printer)
self.monkeyprint(printer)
return PrettyTable(toprow)
def print_result_tabular(result, result_filter=None):
@ -200,16 +141,16 @@ class CloudMonkeyShell(cmd.Cmd, object):
if printer and row:
printer.add_row(row)
if printer:
self.print_shell(printer)
self.monkeyprint(printer)
def print_result_as_dict(result, result_filter=None):
for key in sorted(result.keys(), key=lambda x:
x not in ['id', 'count', 'name'] and x):
if not (isinstance(result[key], list) or
isinstance(result[key], dict)):
self.print_shell("%s = %s" % (key, result[key]))
self.monkeyprint("%s = %s" % (key, result[key]))
else:
self.print_shell(key + ":")
self.monkeyprint(key + ":")
self.print_result(result[key], result_filter)
def print_result_as_list(result, result_filter=None):
@ -220,7 +161,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
break
self.print_result(node)
if len(result) > 1:
self.print_shell(self.ruler * 80)
self.monkeyprint(self.ruler * 80)
if isinstance(result, dict):
print_result_as_dict(result, result_filter)
@ -229,92 +170,18 @@ class CloudMonkeyShell(cmd.Cmd, object):
elif isinstance(result, str):
print result
elif not (str(result) is None):
self.print_shell(result)
def make_request(self, command, requests={}, isAsync=False):
conn = cloudConnection(self.host, port=int(self.port),
apiKey=self.apikey, securityKey=self.secretkey,
asyncTimeout=self.timeout, logging=logger,
protocol=self.protocol, path=self.path)
response = None
logger.debug("====START Request====")
logger.debug("Requesting command=%s, args=%s" % (command, requests))
try:
response = conn.make_request_with_auth(command, requests)
except cloudstackAPIException, e:
self.print_shell("API Error:", e)
except HTTPError, e:
self.print_shell(e)
except (URLError, BadStatusLine), e:
self.print_shell("Connection Error:", e)
logger.debug("====END Request====\n")
def process_json(response):
try:
response = json.loads(str(response))
except ValueError, e:
pass
return response
response = process_json(response)
if response is None:
return
isAsync = isAsync and (self.asyncblock == "true")
responsekey = filter(lambda x: 'response' in x, response.keys())[0]
if isAsync and 'jobid' in response[responsekey]:
jobId = response[responsekey]['jobid']
command = "queryAsyncJobResult"
requests = {'jobid': jobId}
timeout = int(self.timeout)
pollperiod = 3
progress = 1
while timeout > 0:
print '\r' + '.' * progress,
sys.stdout.flush()
response = process_json(conn.make_request_with_auth(command,
requests))
responsekeys = filter(lambda x: 'response' in x,
response.keys())
if len(responsekeys) < 1:
continue
result = response[responsekeys[0]]
jobstatus = result['jobstatus']
if jobstatus == 2:
jobresult = result["jobresult"]
self.print_shell("\rAsync query failed for jobid",
jobId, "\nError", jobresult["errorcode"],
jobresult["errortext"])
return
elif jobstatus == 1:
print '\r',
return response
time.sleep(pollperiod)
timeout = timeout - pollperiod
progress += 1
logger.debug("job: %s to timeout in %ds" % (jobId, timeout))
self.print_shell("Error:", "Async query timeout for jobid", jobId)
self.monkeyprint(result)
def make_request(self, command, args={}, isasync=False):
response, error = monkeyrequest(command, args, isasync,
self.asyncblock, logger,
self.host, self.port,
self.apikey, self.secretkey,
self.timeout, self.protocol, self.path)
if error is not None:
self.monkeyprint(error)
return response
def get_api_module(self, api_name, api_class_strs=[]):
try:
api_mod = __import__("marvin.cloudstackAPI.%s" % api_name,
globals(), locals(), api_class_strs, -1)
except ImportError, e:
self.print_shell("Error: API not found", e)
return None
return api_mod
def pipe_runner(self, args):
if args.find(' |') > -1:
pname = self.program_name
if '.py' in pname:
pname = "python " + pname
self.do_shell("%s %s" % (pname, args))
return True
return False
def default(self, args):
if self.pipe_runner(args):
return
@ -340,31 +207,20 @@ class CloudMonkeyShell(cmd.Cmd, object):
map(lambda x: x.strip(),
args_dict.pop('filter').split(',')))
api_cmd_str = "%sCmd" % api_name
api_mod = self.get_api_module(api_name, [api_cmd_str])
if api_mod is None:
return
try:
api_cmd = getattr(api_mod, api_cmd_str)
except AttributeError, e:
self.print_shell("Error: API attribute %s not found!" % e)
return
for attribute in args_dict.keys():
setattr(api_cmd, attribute, args_dict[attribute])
command = api_cmd()
missing_args = filter(lambda x: x not in args_dict.keys(),
command.required)
#command = api_cmd()
#missing_args = filter(lambda x: x not in args_dict.keys(),
# command.required)
if len(missing_args) > 0:
self.print_shell("Missing arguments: ", ' '.join(missing_args))
return
#if len(missing_args) > 0:
# self.monkeyprint("Missing arguments: ", ' '.join(missing_args))
# return
isAsync = False
if "isAsync" in dir(command):
isAsync = (command.isAsync == "true")
#if "isAsync" in dir(command):
# isAsync = (command.isAsync == "true")
result = self.make_request(api_name, args_dict, isAsync)
if result is None:
@ -375,7 +231,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
self.print_result(result[responsekey], field_filter)
print
except Exception as e:
self.print_shell("🙈 Error on parsing and printing", e)
self.monkeyprint("🙈 Error on parsing and printing", e)
def completedefault(self, text, line, begidx, endidx):
partitions = line.partition(" ")
@ -403,6 +259,17 @@ class CloudMonkeyShell(cmd.Cmd, object):
autocompletions.append("filter=")
return [s for s in autocompletions if s.startswith(search_string)]
def do_sync(self, args):
"""
Asks cloudmonkey to discovery and sync apis available on user specified
CloudStack host server which has the API discovery plugin, on failure
it rollbacks last datastore or api precached datastore.
"""
response = self.make_request("listApis")
f = open('test.json', "w")
f.write(json.dumps(response))
f.close()
def do_api(self, args):
"""
Make raw api calls. Syntax: api <apiName> <args>=<values>.
@ -413,7 +280,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
if len(args) > 0:
return self.default(args)
else:
self.print_shell("Please use a valid syntax")
self.monkeyprint("Please use a valid syntax")
def complete_api(self, text, line, begidx, endidx):
mline = line.partition(" ")[2]
@ -435,7 +302,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
key, value = (args[0], args[2])
setattr(self, key, value) # keys and attributes should have same names
self.prompt = self.prompt.strip() + " " # prompt fix
self.write_config()
write_config(self.get_attr)
def complete_set(self, text, line, begidx, endidx):
mline = line.partition(" ")[2]
@ -443,6 +310,15 @@ class CloudMonkeyShell(cmd.Cmd, object):
return [s[offs:] for s in self.config_options
if s.startswith(mline)]
def pipe_runner(self, args):
if args.find(' |') > -1:
pname = self.program_name
if '.py' in pname:
pname = "python " + pname
self.do_shell("%s %s" % (pname, args))
return True
return False
def do_shell(self, args):
"""
Execute shell commands using shell <command> or !<command>
@ -474,9 +350,9 @@ class CloudMonkeyShell(cmd.Cmd, object):
subject = fields[2].partition(" ")[0]
if subject in self.cache_verbs[verb]:
self.print_shell(self.cache_verbs[verb][subject][2])
self.monkeyprint(self.cache_verbs[verb][subject][2])
else:
self.print_shell("Error: no such api (%s) on %s" %
self.monkeyprint("Error: no such api (%s) on %s" %
(subject, verb))
def complete_help(self, text, line, begidx, endidx):
@ -500,7 +376,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
"""
Quit CloudMonkey CLI
"""
self.print_shell("Bye!")
self.monkeyprint("Bye!")
return self.do_EOF(args)
def do_EOF(self, args):
@ -526,10 +402,10 @@ def main():
helpdoc = res[2]
args = args_partition[2]
except KeyError, e:
self.print_shell("Error: invalid %s api arg" % verb, e)
self.monkeyprint("Error: invalid %s api arg" % verb, e)
return
if ' --help' in args or ' -h' in args:
self.print_shell(helpdoc)
self.monkeyprint(helpdoc)
return
self.default("%s %s" % (cmd, args))
return grammar_closure

View File

@ -21,8 +21,11 @@
__version__ = "4.1.0-0"
try:
from os.path import expanduser
import os
import sys
from ConfigParser import ConfigParser, SafeConfigParser
from os.path import expanduser
from precache import precached_verbs
except ImportError, e:
precached_verbs = {}
@ -30,6 +33,8 @@ except ImportError, e:
param_type = ['boolean', 'date', 'float', 'integer', 'short', 'list',
'long', 'object', 'map', 'string', 'tzdate', 'uuid']
iterable_type = ['set', 'list', 'object']
config_dir = expanduser('~/.cloudmonkey')
config_file = expanduser(config_dir + '/config')
@ -57,3 +62,54 @@ config_fields['server']['timeout'] = '3600'
# user
config_fields['user']['apikey'] = ''
config_fields['user']['secretkey'] = ''
def write_config(get_attr, first_time=False):
global config_fields, config_file
config = ConfigParser()
for section in config_fields.keys():
config.add_section(section)
for key in config_fields[section].keys():
if first_time:
config.set(section, key, config_fields[section][key])
else:
config.set(section, key, get_attr(key))
with open(config_file, 'w') as cfg:
config.write(cfg)
return config
def read_config(get_attr, set_attr):
global config_fields, config_dir, config_file
if not os.path.exists(config_dir):
os.makedirs(config_dir)
config_options = reduce(lambda x, y: x + y, map(lambda x:
config_fields[x].keys(), config_fields.keys()))
if os.path.exists(config_file):
config = ConfigParser()
try:
with open(config_file, 'r') as cfg:
config.readfp(cfg)
except IOError, e:
print "Error: config_file not found", e
else:
config = write_config(get_attr, True)
print "Welcome! Using `set` configure the necessary settings:"
print " ".join(sorted(config_options))
print "Config file:", config_file
missing_keys = []
for section in config_fields.keys():
for key in config_fields[section].keys():
try:
set_attr(key, config.get(section, key))
except Exception:
missing_keys.appned(key)
if len(missing_keys) > 0:
print "Please fix `%s` in %s" % (key, config_file)
sys.exit()
return config_options

View File

@ -25,6 +25,7 @@ try:
from pygments.token import *
import sys
import types
except ImportError, e:
print e
@ -92,7 +93,6 @@ class MonkeyFormatter(Formatter):
self.colorscheme = get_colorscheme()
def format(self, tokensource, outfile):
self.encoding = outfile.encoding
return Formatter.format(self, tokensource, outfile)
def format_unencoded(self, tokensource, outfile):
@ -113,9 +113,21 @@ class MonkeyFormatter(Formatter):
outfile.write(value)
def monkeyprint(text):
def monkeyprint(color=True, *args):
fmter = MonkeyFormatter()
lexer = MonkeyLexer()
lexer.encoding = 'utf-8'
fmter.encoding = 'utf-8'
highlight(text, lexer, fmter, sys.stdout)
output = ""
try:
for arg in args:
if isinstance(type(arg), types.NoneType):
continue
output += str(arg)
except Exception, e:
print e
if color:
highlight(output, lexer, fmter, sys.stdout)
else:
print output

View File

@ -0,0 +1,153 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
try:
import base64
import hashlib
import hmac
import httplib
import json
import os
import pdb
import re
import shlex
import sys
import time
import types
import urllib
import urllib2
except ImportError, e:
print "Import error in %s : %s" % (__name__, e)
import sys
sys.exit()
def logger_debug(logger, message):
if logger is not None:
logger.debug(message)
def make_request(command, args, logger, host, port,
apikey, secretkey, protocol, path):
response = None
error = None
if protocol != 'http' and protocol != 'https':
error = "Protocol must be 'http' or 'https'"
return None, error
if args is None:
args = {}
args["command"] = command
args["apiKey"] = apikey
args["response"] = "json"
request = zip(args.keys(), args.values())
request.sort(key=lambda x: str.lower(x[0]))
request_url = "&".join(["=".join([r[0], urllib.quote_plus(str(r[1]))])
for r in request])
hashStr = "&".join(["=".join([str.lower(r[0]),
str.lower(urllib.quote_plus(str(r[1]))).replace("+",
"%20")]) for r in request])
sig = urllib.quote_plus(base64.encodestring(hmac.new(secretkey, hashStr,
hashlib.sha1).digest()).strip())
request_url += "&signature=%s" % sig
request_url = "%s://%s:%s%s?%s" % (protocol, host, port, path, request_url)
try:
logger_debug(logger, "Request sent: %s" % request_url)
connection = urllib2.urlopen(request_url)
response = connection.read()
except Exception, e:
error = str(e)
logger_debug(logger, "Response received: %s" % response)
if error is not None:
logger_debug(logger, error)
return response, error
def monkeyrequest(command, args, isasync, asyncblock, logger, host, port,
apikey, secretkey, timeout, protocol, path):
response = None
error = None
logger_debug(logger, "======== START Request ========")
logger_debug(logger, "Requesting command=%s, args=%s" % (command, args))
response, error = make_request(command, args, logger, host, port,
apikey, secretkey, protocol, path)
logger_debug(logger, "======== END Request ========\n")
if error is not None:
return response, error
def process_json(response):
try:
response = json.loads(str(response))
except ValueError, e:
error = "Error processing json response, %s" % e
logger_debug(logger, "Error processing json", e)
return response
response = process_json(response)
if response is None:
return response, error
isasync = isasync and (asyncblock == "true")
responsekey = filter(lambda x: 'response' in x, response.keys())[0]
if isasync and 'jobid' in response[responsekey]:
jobid = response[responsekey]['jobid']
command = "queryAsyncJobResult"
request = {'jobid': jobid}
timeout = int(timeout)
pollperiod = 3
progress = 1
while timeout > 0:
print '\r' + '.' * progress,
time.sleep(pollperiod)
timeout = timeout - pollperiod
progress += 1
logger_debug(logger, "Job %s to timeout in %ds" % (jobid, timeout))
sys.stdout.flush()
response, error = monkeyrequest(command, request, isasync,
asyncblock, logger,
host, port, apikey, secretkey,
timeout, protocol, path)
response = process_json(response)
responsekeys = filter(lambda x: 'response' in x, response.keys())
if len(responsekeys) < 1:
continue
result = response[responsekeys[0]]
jobstatus = result['jobstatus']
if jobstatus == 2:
jobresult = result["jobresult"]
error = "\rAsync job %s failed\nError %s, %s" % (jobid,
jobresult["errorcode"], jobresult["errortext"])
return response, error
elif jobstatus == 1:
print '\r',
return response, error
error = "Error: Async query timeout occurred for jobid %s" % jobid
return response, error

View File

@ -72,7 +72,7 @@
</configuration>
</execution>
<execution>
<id>cachegen</id>
<id>cachemaker</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
@ -81,7 +81,7 @@
<workingDirectory>${basedir}/cloudmonkey</workingDirectory>
<executable>python</executable>
<arguments>
<argument>cachegen.py</argument>
<argument>cachemaker.py</argument>
</arguments>
</configuration>
</execution>