| #!/usr/bin/python |
| |
| import os |
| import pdb |
| import sys |
| import json |
| |
| sys.path.append('.') |
| |
| os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings") |
| |
| from django.db.models.fields.related import ForeignKey |
| |
| # try to make sure we're running from the right place |
| if (not os.path.exists("core")): |
| if (os.path.exists("../core")): |
| os.chdir("..") |
| else: |
| print >> sys.stderr, "Are you sure you're running dmdot from the root of an XOS installation" |
| sys.exit(-1) |
| |
| from core.models import ModelLink |
| |
| # defaults |
| apps = ["core"]#, "services.hpc", "services.requestrouter", "services.onos"] |
| output = "-json" |
| |
| # syntax: mldeps [-json | -dot] [app_name] |
| |
| # poor man's argument parser |
| for arg in sys.argv[1:]: |
| if arg.startswith("-"): |
| output = arg |
| else: |
| apps+= [arg] |
| |
| model_classes = [] |
| class_names = [] |
| lower_class_names = {} |
| synonyms = { |
| 'user':'creator' |
| } |
| |
| for app in apps: |
| app = app + ".models" |
| #models_module = imp.load_source(app, ".") |
| models_module = __import__(app) |
| for part in app.split(".")[1:]: |
| if hasattr(models_module, "PlCoreBase"): |
| break |
| models_module = getattr(models_module,part) |
| |
| PlCoreBase = getattr(models_module,"PlCoreBase") |
| |
| for classname in dir(models_module): |
| c = getattr(models_module, classname, None) |
| if type(c)==type(PlCoreBase): |
| model_classes.append(c) |
| class_names.append(c.__name__) |
| lower_class_names[c.__name__.lower()] = c |
| try: |
| synonym = synonyms[c.__name__.lower()] |
| lower_class_names[synonym] = c |
| except: |
| pass |
| |
| # django doesn't use the correct case in field.name.title() for objects that |
| # have CamelCased class names. So, compare everything in lower case. |
| |
| if (output=='-dot'): |
| print "digraph plstack {"; |
| for c in model_classes: |
| fields = c._meta.fields |
| |
| for f in fields: |
| if type(f)==ForeignKey and f.name.lower().split('_') in lower_class_names: |
| linked_class = lower_class_names[f.name.lower()] |
| if ('backref' in f.name): |
| print '\t"%s"->"%s";'%(linked_class.__name__,c.__name__) |
| else: |
| print '\t"%s"->"%s";'%(c.__name__,linked_class.__name__) |
| print "}\n"; |
| elif (output=='-json'): |
| d = {} |
| tl = {} |
| for c in model_classes: |
| fields = c._meta.fields |
| try: |
| exp_links = c.xos_links |
| except AttributeError: |
| exp_links = [] |
| for f in fields: |
| field_type = f.name.lower().split('_')[0] |
| if type(f)==ForeignKey and field_type in lower_class_names: |
| linked_class = lower_class_names[field_type] |
| |
| |
| if ('backref' in f.name.lower()): |
| a = linked_class.__name__ |
| b = c.__name__ |
| else: |
| b = linked_class.__name__ |
| a = c.__name__ |
| |
| try: |
| |
| if (b not in d[a]): |
| d[a].append(b) |
| except KeyError: |
| d[c.__name__]=[linked_class.__name__] |
| |
| for l in exp_links: |
| linked_class = l.dest |
| if (type(linked_class)==str): |
| linked_class = lower_class_names[linked_class.lower()] |
| via = l.via |
| if ('backref' in via): |
| a = linked_class.__name__ |
| b = c.__name__ |
| else: |
| b = linked_class.__name__ |
| a = c.__name__ |
| |
| try: |
| if (b not in tl[a]): |
| tl[a].append(b) |
| except KeyError: |
| tl[c.__name__]=[linked_class.__name__] |
| |
| |
| #d['ControllerNetwork'].append('SliceDeployments') |
| print json.dumps(tl,indent=4) |