| # -*- 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 types |
| |
| from config import config_fields |
| 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 splitcsvstring(string): |
| if string is not None: |
| return filter(lambda x: x.strip() != '', string.split(',')) |
| else: |
| return [] |
| |
| |
| def splitverbsubject(string): |
| idx = 0 |
| for char in string: |
| if char.islower(): |
| idx += 1 |
| else: |
| break |
| return string[:idx].lower(), string[idx:].lower() |
| |
| |
| def savecache(apicache, json_file): |
| """ |
| Saves apicache dictionary as json_file, returns dictionary as indented str |
| """ |
| if apicache is None or apicache is {}: |
| return "" |
| apicachestr = json.dumps(apicache, indent=2) |
| with open(json_file, 'w') as cache_file: |
| cache_file.write(apicachestr) |
| return apicachestr |
| |
| |
| def loadcache(json_file): |
| """ |
| Loads json file as dictionary, feeds it to monkeycache and spits result |
| """ |
| f = open(json_file, 'r') |
| data = f.read() |
| f.close() |
| try: |
| apicache = json.loads(data) |
| except ValueError, e: |
| print "Error processing json:", json_file, e |
| return {} |
| return apicache |
| |
| |
| def monkeycache(apis): |
| """ |
| Feed this a dictionary of api bananas, it spits out processed cache |
| """ |
| if isinstance(type(apis), types.NoneType) or apis is None: |
| return {} |
| |
| responsekey = filter(lambda x: 'response' in x, apis.keys()) |
| |
| if len(responsekey) == 0: |
| print "[monkeycache] Invalid dictionary, has no response" |
| return None |
| if len(responsekey) != 1: |
| print "[monkeycache] Multiple responsekeys, chosing first one" |
| |
| responsekey = responsekey[0] |
| verbs = set() |
| cache = {} |
| cache['count'] = getvalue(apis[responsekey], 'count') |
| cache['asyncapis'] = [] |
| |
| apilist = getvalue(apis[responsekey], 'api') |
| if apilist is None: |
| print "[monkeycache] Server response issue, no apis found" |
| |
| for api in apilist: |
| name = getvalue(api, 'name') |
| verb, subject = splitverbsubject(name) |
| |
| apidict = {} |
| apidict['name'] = name |
| apidict['description'] = getvalue(api, 'description') |
| apidict['isasync'] = getvalue(api, 'isasync') |
| if apidict['isasync']: |
| cache['asyncapis'].append(name) |
| apidict['related'] = splitcsvstring(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'] = splitcsvstring(getvalue(param, 'related')) |
| if apiparam['required']: |
| required.append(apiparam['name']) |
| apiparams.append(apiparam) |
| |
| apidict['requiredparams'] = required |
| apidict['params'] = apiparams |
| if verb not in cache: |
| cache[verb] = {} |
| cache[verb][subject] = apidict |
| verbs.add(verb) |
| |
| cache['verbs'] = list(verbs) |
| return cache |
| |
| |
| def main(json_file): |
| """ |
| cachemaker.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 cachemaker.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("\napicache = %s" % loadcache(json_file)) |
| f.close() |
| |
| if __name__ == "__main__": |
| cache_file = config_fields['core']['cache_file'] |
| print "[cachemaker] Pre-caching using user's cloudmonkey cache", cache_file |
| if os.path.exists(cache_file): |
| main(cache_file) |
| else: |
| print "[cachemaker] Unable to cache apis, file not found", cache_file |
| print "[cachemaker] Run cloudmonkey sync to generate cache" |