fix relative directory paths and add common/libexec
This commit is contained in:
parent
7ef120d30c
commit
6c65d4e278
@ -0,0 +1,57 @@
|
||||
from .Normalization import Normalization
|
||||
from .core.Guid import Guid
|
||||
|
||||
class InstanceCache:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.next_inst_id = dict()
|
||||
self.next_inst_id[1] = 1
|
||||
|
||||
self.inst_indices = dict()
|
||||
self.inst_guids = dict()
|
||||
|
||||
self.dbids_gid = dict()
|
||||
|
||||
def add_instance(self, inst_key, inst_gid):
|
||||
self.inst_guids[inst_key] = inst_gid
|
||||
self.inst_indices[inst_gid] = inst_key
|
||||
|
||||
if not inst_key[0] in self.next_inst_id:
|
||||
self.next_inst_id[inst_key[0]] = 1
|
||||
|
||||
if inst_key[1] >= self.next_inst_id[inst_key[0]]:
|
||||
self.next_inst_id[inst_key[0]] = inst_key[1] + 1
|
||||
|
||||
def get_global_identifier(self, inst_key):
|
||||
return self.inst_guids[inst_key]
|
||||
|
||||
def get_instance_key(self, inst_gid):
|
||||
return self.inst_indices[inst_gid]
|
||||
|
||||
def get_next_instance_id(self, class_index):
|
||||
if not class_index in self.next_inst_id:
|
||||
# this is the first instance of this class
|
||||
self.next_inst_id[class_index] = 1
|
||||
|
||||
val = self.next_inst_id[class_index]
|
||||
self.next_inst_id[class_index] += 1
|
||||
return val
|
||||
|
||||
def has_instance_by_global_identifier(self, gid):
|
||||
return gid in self.inst_indices
|
||||
|
||||
def count(self) -> int:
|
||||
"""
|
||||
Returns the number of instances stored in this OMS.
|
||||
"""
|
||||
return len(self.inst_indices)
|
||||
|
||||
def get_instance_keys(self):
|
||||
return self.inst_indices
|
||||
|
||||
def set_database_id_by_global_identifier(self, gid : Guid, dbid):
|
||||
self.dbids_gid[Normalization.normalize_uuid(gid.get_value())] = dbid
|
||||
# self.dbids_idx[self.inst_indices[gid]] = dbid
|
||||
def get_database_id_by_global_identifier(self, gid : Guid):
|
||||
return self.dbids_gid[Normalization.normalize_uuid(gid.get_value())]
|
||||
@ -0,0 +1,443 @@
|
||||
import MySQLdb
|
||||
|
||||
from .libraryparser import XMLLibraryParser, JSONLibraryParser, YAMLLibraryParser
|
||||
|
||||
from .LibraryOperation import LibraryOperation
|
||||
from .operations.AssignAttributeOperation import AssignAttributeOperation
|
||||
from .operations.AssignRelationshipOperation import AssignRelationshipOperation
|
||||
from .operations.PrepareInstanceOperation import PrepareInstanceOperation
|
||||
from .operations.StoredProcedureOperation import StoredProcedureOperation
|
||||
|
||||
from .Normalization import Normalization
|
||||
|
||||
from .core.Guid import Guid
|
||||
from .core.KnownClassGuids import IDC_EntityDefinition, IDC_SourceDefinition
|
||||
from .core.KnownAttributeGuids import *
|
||||
from .core.KnownRelationshipGuids import *
|
||||
|
||||
from .InstanceCache import InstanceCache
|
||||
from .SQLExpression import SQLExpression
|
||||
|
||||
from redis import Redis
|
||||
|
||||
class MochaLibraryManager:
|
||||
|
||||
def __init__(self):
|
||||
self.entityReferences = dict()
|
||||
self.entityReferenceFileNames = dict()
|
||||
self.db = None
|
||||
self._instances = []
|
||||
self._attOps = []
|
||||
self._relOps = []
|
||||
self.redis = None
|
||||
|
||||
def connect(self, hostname, database, username, password):
|
||||
self.db = MySQLdb.connect(host=hostname, user=username, passwd=password, db=database)
|
||||
self.redis = Redis(host=hostname, port=6379, decode_responses=True)
|
||||
|
||||
def process_instance_ops(self):
|
||||
# this version is much faster as it prepares everything in advanced on the CPU before
|
||||
# pushing it out to the database
|
||||
|
||||
instances = InstanceCache()
|
||||
|
||||
for key in self._instances:
|
||||
(class_gid, inst_gid, class_index, inst_index) = key
|
||||
# first import all the known classes
|
||||
if class_gid is not None and class_index is not None:
|
||||
# print ("known class import")
|
||||
# print ("class_gid = " + class_gid)
|
||||
# print ("inst_gid = " + inst_gid + " (" + str(class_index) + "$" + str(inst_index) + ")")
|
||||
if not instances.has_instance_by_global_identifier(class_gid):
|
||||
instances.add_instance((1, class_index), class_gid)
|
||||
|
||||
for key in self._instances:
|
||||
(class_gid, inst_gid, class_index, inst_index) = key
|
||||
# now get all the classes without specified IIDs
|
||||
if class_gid is not None and class_index is None:
|
||||
# print ("unknown class import")
|
||||
if not instances.has_instance_by_global_identifier(class_gid):
|
||||
class_index = instances.get_next_instance_id(class_index)
|
||||
else:
|
||||
class_index = instances.get_instance_key(class_gid)[1]
|
||||
|
||||
if inst_index is None:
|
||||
inst_index = instances.get_next_instance_id(class_index)
|
||||
|
||||
instances.add_instance((1, inst_index), inst_gid)
|
||||
|
||||
# print ("class_gid = " + class_gid)
|
||||
# print ("inst_gid = " + inst_gid + " (" + str(1) + "$" + str(inst_index) + ")")
|
||||
|
||||
for key in self._instances:
|
||||
(class_gid, inst_gid, class_index, inst_index) = key
|
||||
if class_gid is not None and class_index is not None and inst_gid is not None and inst_index is not None:
|
||||
# we know all there is to know about this one
|
||||
pass
|
||||
elif class_gid is not None and inst_gid is not None:
|
||||
if class_index is None:
|
||||
# we need to know the class index
|
||||
if instances.has_instance_by_global_identifier(class_gid):
|
||||
class_index = instances.get_instance_key(class_gid)[1]
|
||||
else:
|
||||
class_index = instances.get_next_instance_id(1)
|
||||
|
||||
if inst_index is None:
|
||||
# we need to know the instance index as well
|
||||
if instances.has_instance_by_global_identifier(inst_gid):
|
||||
inst_index = instances.get_instance_key(inst_gid)[1]
|
||||
else:
|
||||
inst_index = instances.get_next_instance_id(class_index)
|
||||
else:
|
||||
print("error: not implemened class_gid is None or inst_gid is None")
|
||||
|
||||
instances.add_instance((class_index, inst_index), inst_gid)
|
||||
|
||||
print (str(instances.count()) + " instances preloaded")
|
||||
|
||||
c = 0
|
||||
query = "INSERT INTO mocha_instances (tenant_id, class_id, inst_id, global_identifier) VALUES "
|
||||
for inst_gid in instances.get_instance_keys():
|
||||
(class_index, inst_index) = instances.get_instance_key(inst_gid)
|
||||
print("preparing inst " + str(class_index) + "$" + str(inst_index) + " with guid " + inst_gid)
|
||||
|
||||
inst_key_str = str(class_index) + "$" + str(inst_index)
|
||||
self.redis.set(inst_key_str + ".gid", Normalization.normalize_uuid(inst_gid))
|
||||
self.redis.set(inst_key_str + ".attributes.count", "0")
|
||||
self.redis.set(inst_key_str + ".relationships.count", "0")
|
||||
self.redis.set(Normalization.normalize_uuid(inst_gid) + ".iid", inst_key_str)
|
||||
self.redis.set(Normalization.normalize_uuid(inst_gid) + ".attributes.count", "0")
|
||||
self.redis.set(Normalization.normalize_uuid(inst_gid) + ".relationships.count", "0")
|
||||
|
||||
query += "(1, " + str(class_index) + ", " + str(inst_index) + ", '" + Normalization.normalize_uuid(inst_gid) + "')"
|
||||
|
||||
if c < instances.count() - 1:
|
||||
query += ", "
|
||||
|
||||
c += 1
|
||||
|
||||
print ("process_instance_ops: query was: ")
|
||||
print (query)
|
||||
self.db.query(query)
|
||||
|
||||
self.instances = instances
|
||||
return True
|
||||
|
||||
def process_attribute_ops(self, ops):
|
||||
query = "INSERT INTO mocha_attributes (tenant_id, src_inst_id, att_inst_id, usr_inst_id, att_effective_date, att_value) VALUES "
|
||||
for op in ops:
|
||||
instanceId = op.instanceId
|
||||
attributeInstanceId = op.attributeInstanceId
|
||||
value = op.value
|
||||
|
||||
if attributeInstanceId.get_value() == "":
|
||||
print("skipping invalid blank attribute")
|
||||
continue
|
||||
|
||||
print (instanceId.get_value() + " : " + attributeInstanceId.get_value() + " = '" + str(value) + "'")
|
||||
|
||||
# query += "(1, " \
|
||||
# + "mocha_get_instance_by_global_identifier('" + Normalization.normalize_uuid(instanceId.get_value()) + "'), " \
|
||||
# + "mocha_get_instance_by_global_identifier('" + Normalization.normalize_uuid(attributeInstanceId.get_value()) + "'), " \
|
||||
# + "NULL, NOW(), " + SQLExpression.normalize_parm(value) + ")"
|
||||
|
||||
query += "(1, " \
|
||||
+ str(self.instances.get_database_id_by_global_identifier(instanceId)) + ", " \
|
||||
+ str(self.instances.get_database_id_by_global_identifier(attributeInstanceId)) + ", " \
|
||||
+ "NULL, NOW(), " + SQLExpression.normalize_parm(value) + ")"
|
||||
|
||||
if ops.index(op) < len(ops) - 1:
|
||||
query += ", "
|
||||
|
||||
# op.execute(self.db)
|
||||
|
||||
print ("process_attribute_ops: query was: ")
|
||||
print (query)
|
||||
self.db.query(query)
|
||||
|
||||
def process_relationship_ops(self, ops):
|
||||
query = "INSERT INTO mocha_relationships (tenant_id, source_inst_id, relationship_inst_id, destination_inst_id, user_inst_id, effective_date) VALUES "
|
||||
|
||||
for op in ops:
|
||||
instanceId = op.instanceId
|
||||
relationshipInstanceId = op.relationshipInstanceId
|
||||
targetInstanceId = op.targetInstanceId
|
||||
|
||||
print (instanceId.get_value() + " : " + relationshipInstanceId.get_value() + " = " + targetInstanceId.get_value())
|
||||
|
||||
query += "(1, " \
|
||||
+ str(self.instances.get_database_id_by_global_identifier(instanceId)) + ", " \
|
||||
+ str(self.instances.get_database_id_by_global_identifier(relationshipInstanceId)) + ", " \
|
||||
+ str(self.instances.get_database_id_by_global_identifier(targetInstanceId)) + ", " \
|
||||
+ "NULL, NOW() )"
|
||||
|
||||
if ops.index(op) < len(ops) - 1:
|
||||
query += ", "
|
||||
|
||||
# op.execute(self.db)
|
||||
|
||||
print ("process_relationship_ops: query was: ")
|
||||
print (query)
|
||||
self.db.query(query)
|
||||
|
||||
def before_commit(self):
|
||||
"""
|
||||
Called before the unstructured information is sorted and written to the database.
|
||||
---
|
||||
This is your last chance to add instances, set attributes, and assign
|
||||
relationships before the compilation is finalized. After this stage, calls made
|
||||
to modify the compilation are undefined and will almost certainly not do what you
|
||||
want.
|
||||
"""
|
||||
|
||||
self.write_debug_information()
|
||||
|
||||
def write_debug_information(self):
|
||||
"""
|
||||
Writes debugging information, such as entity definitions ('&IDC_...;') and source
|
||||
code definitions (filename, line number, column number, etc.)
|
||||
"""
|
||||
|
||||
print ("preparing debug information (use --no-debug or undefine DEBUG or etc. [NOT IMPLEMENTED] to turn off)")
|
||||
for key in self.entityReferences:
|
||||
val = self.entityReferences[key]
|
||||
|
||||
gidEntityDefinition = Guid.create()
|
||||
self.add_instance(IDC_EntityDefinition, gidEntityDefinition, None, None)
|
||||
self.set_attribute_value(gidEntityDefinition, IDA_Name, key)
|
||||
self.set_attribute_value(gidEntityDefinition, IDA_Value, val)
|
||||
|
||||
gidSourceDefinition = Guid.create()
|
||||
self.add_instance(IDC_SourceDefinition, gidSourceDefinition, None, None)
|
||||
self.set_attribute_value(gidSourceDefinition, IDA_DebugDefinitionFileName, self.entityReferenceFileNames[key])
|
||||
|
||||
self.assign_relationship(gidEntityDefinition, IDR_Instance__has__Source_Definition, gidSourceDefinition)
|
||||
|
||||
# Source Definition.has X
|
||||
# self.add_instance(KnownClassGuids.CLASS, Guid("{dc0a5dd2-22e0-471f-87cf-a5ef1b764efa}"), 1, index)
|
||||
# self.assign_relationship(instGid, Guid("{dc0a5dd2-22e0-471f-87cf-a5ef1b764efa}"), targetInstanceId)
|
||||
|
||||
def commit(self):
|
||||
|
||||
self.before_commit()
|
||||
|
||||
# first record all the instances
|
||||
if not self.process_instance_ops():
|
||||
return False
|
||||
|
||||
print("reading database ids...")
|
||||
query = "SELECT id, global_identifier FROM mocha_instances"
|
||||
|
||||
cur = self.db.cursor()
|
||||
cur.execute(query)
|
||||
rows = cur.fetchall()
|
||||
|
||||
for (dbid, gid) in rows:
|
||||
self.instances.set_database_id_by_global_identifier(Guid(gid), dbid)
|
||||
|
||||
print("assigning attributes...")
|
||||
self.process_attribute_ops(self._attOps)
|
||||
|
||||
print("assigning relationships...")
|
||||
self.process_relationship_ops(self._relOps)
|
||||
|
||||
hasSiblingRelationships = dict()
|
||||
for op in self._relOps:
|
||||
relationshipKey = self.instances
|
||||
|
||||
if op.relationshipInstanceId.get_value() == "{656110FF-4502-48B8-A7F3-D07F017AEA3F}":
|
||||
# Relationship.has sibling Relationship
|
||||
hasSiblingRelationships[op.instanceId.get_value()] = op.targetInstanceId
|
||||
|
||||
siblingOps = []
|
||||
for op in self._relOps:
|
||||
if op.relationshipInstanceId.get_value() in hasSiblingRelationships:
|
||||
siblingOp = AssignRelationshipOperation(op.targetInstanceId, hasSiblingRelationships[op.relationshipInstanceId.get_value()], op.instanceId)
|
||||
siblingOps.append(siblingOp)
|
||||
# print ("assigning sibling relationship " + siblingOp.instanceId.get_value() + " . " + siblingOp.relationshipInstanceId.get_value() + " = " + siblingOp.instanceId.get_value())
|
||||
# siblingOp.execute(self.db)
|
||||
|
||||
print("assigning sibling relationships...")
|
||||
self.process_relationship_ops(siblingOps)
|
||||
|
||||
print("setting creation user...")
|
||||
|
||||
cur = self.db.cursor()
|
||||
# cur.execute("UPDATE mocha_instances SET user_inst_id = mocha_get_instance_by_global_identifier(mocha_normalize_uuid('{B066A54B-B160-4510-A805-436D3F90C2E6}'))")
|
||||
cur.execute("UPDATE mocha_attributes SET usr_inst_id = " + str(self.instances.get_database_id_by_global_identifier(Guid("{B066A54B-B160-4510-A805-436D3F90C2E6}"))))
|
||||
cur.execute("UPDATE mocha_relationships SET user_inst_id = " + str(self.instances.get_database_id_by_global_identifier(Guid("{B066A54B-B160-4510-A805-436D3F90C2E6}"))))
|
||||
# rows = cur.fetchall()
|
||||
# print(rows)
|
||||
|
||||
# print ("ok , applying `Class.has Instance`...")
|
||||
|
||||
# for row in rows:
|
||||
# print(row)
|
||||
# id = row[0]
|
||||
# tenant_id = row[1]
|
||||
# class_id = row[2]
|
||||
# inst_id = row[3]
|
||||
# global_identifier = row[4]
|
||||
|
||||
# if class_id is not None and id is not None:
|
||||
|
||||
# # Class.has Instance
|
||||
# query2 = ("CALL mocha_assign_relationship (" +
|
||||
# "mocha_get_instance_by_key(1, " + str(class_id) + "), " +
|
||||
# "mocha_get_instance_by_global_identifier(mocha_normalize_uuid('7EB41D3C-2AE9-4884-83A4-E59441BCAEFB'))" + ", " +
|
||||
# str(id) + ", NULL, NULL)")
|
||||
# cur.execute(query2)
|
||||
|
||||
# # Instance.for Class
|
||||
# query3 = ("CALL mocha_assign_relationship (" +
|
||||
# str(id) + ", " +
|
||||
# "mocha_get_instance_by_global_identifier(mocha_normalize_uuid('494D5A6D-04BE-477B-8763-E3F57D0DD8C8'))" + ", " +
|
||||
# "mocha_get_instance_by_key(1, " + str(class_id) + "), NULL, NULL)")
|
||||
# cur.execute(query3)
|
||||
|
||||
self.db.commit()
|
||||
|
||||
def close(self):
|
||||
self.db.close()
|
||||
|
||||
def print_error(self, cur):
|
||||
rows = cur.fetchall()
|
||||
for row in rows:
|
||||
if 'error_description' in row:
|
||||
print (row['error_description'])
|
||||
|
||||
def select_tenant(self, tenantName):
|
||||
cur = self.db.cursor()
|
||||
cur.execute("CALL mocha_select_tenant(mocha_get_tenant_by_name('" + tenantName + "'))")
|
||||
self.print_error(cur)
|
||||
|
||||
def release_tenant(self):
|
||||
cur = self.db.cursor()
|
||||
cur.execute("CALL mocha_release_tenant()")
|
||||
self.print_error(cur)
|
||||
|
||||
def assign_relationship(self, instanceId : Guid, relationshipInstanceId : Guid, targetInstanceId : Guid):
|
||||
print("-- assigning relationship " + relationshipInstanceId.get_value() + " = '" + targetInstanceId.get_value() + "'")
|
||||
self._relOps.append(AssignRelationshipOperation(instanceId, relationshipInstanceId, targetInstanceId))
|
||||
# self._relOps.append(AssignRelationshipOperation(instanceId, relationshipInstanceId, targetInstanceId))
|
||||
# query = "CALL mocha_assign_relationship(mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + instanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + relationshipInstanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + targetInstanceId.get_value() + "')), NULL, NULL);"
|
||||
# print(query)
|
||||
# cur.execute(query)
|
||||
# self.print_error(cur)
|
||||
|
||||
def set_attribute_value(self, instanceId : Guid, attributeInstanceId : Guid, value):
|
||||
print("-- assigning attribute " + attributeInstanceId.get_value() + " = '" + str(value) + "'")
|
||||
self._attOps.append(AssignAttributeOperation(instanceId, attributeInstanceId, value))
|
||||
|
||||
def install_from_path(self, path):
|
||||
|
||||
from glob import glob
|
||||
|
||||
xl = XMLLibraryParser(self)
|
||||
jl = JSONLibraryParser(self)
|
||||
yl = YAMLLibraryParser(self)
|
||||
|
||||
#xml_files = glob(path + "/**/*.xml", recursive=True)
|
||||
#for xml_file in xml_files:
|
||||
#s xl.load_file(xml_file)
|
||||
|
||||
|
||||
#json_files = glob(path + "/**/*.json", recursive=True)
|
||||
#for json_file in json_files:
|
||||
# jl.load_file(json_file)
|
||||
|
||||
yaml_files = sorted(glob(path + "/**/*.yaml", recursive=True))
|
||||
if len(yaml_files) == 0:
|
||||
print ("no files found ; does the path exist?")
|
||||
return 3
|
||||
|
||||
# first, load the entity defs
|
||||
for yaml_file in yaml_files:
|
||||
yl.load_entity_definitions_from_file(yaml_file)
|
||||
|
||||
try:
|
||||
# then, load instance definitions (also loads sugar elements into memory for later use)
|
||||
for yaml_file in yaml_files:
|
||||
yl.load_instances_from_file(yaml_file)
|
||||
|
||||
# finally, apply syntactic sugar
|
||||
yl.apply_sugar()
|
||||
|
||||
return True
|
||||
|
||||
except NameError as ex:
|
||||
|
||||
print (ex)
|
||||
|
||||
rgx = "&(.*);"
|
||||
|
||||
# go through and get all entity references across all files
|
||||
import re
|
||||
import fileinput
|
||||
|
||||
stuff = []
|
||||
|
||||
for yaml_file in yaml_files:
|
||||
f = open(yaml_file, "r")
|
||||
text = f.read()
|
||||
matches = re.findall(rgx, text)
|
||||
for match in matches:
|
||||
stuff.append(match)
|
||||
f.close()
|
||||
|
||||
missingEntities = []
|
||||
for stuf in stuff:
|
||||
if not stuf in self.entityReferences:
|
||||
if not stuf in missingEntities:
|
||||
missingEntities.append(stuf)
|
||||
|
||||
if len(missingEntities) > 0:
|
||||
print("\nNOTE: there were undefined referenced entities:\n")
|
||||
for missingEntity in missingEntities:
|
||||
print("\t" + missingEntity)
|
||||
print("\n")
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def exists_entity_reference(self, name):
|
||||
return name in self.entityReferences
|
||||
|
||||
def register_entity_reference(self, name, value, filename = None):
|
||||
self.entityReferences[name] = value
|
||||
self.entityReferenceFileNames[name] = filename
|
||||
|
||||
def define_entity_reference(self, name):
|
||||
return self.entityReferences[name]
|
||||
def expand_entity_references(self, value):
|
||||
insideName = False
|
||||
name = ""
|
||||
retval = ""
|
||||
for i in range(0, len(value)):
|
||||
if value[i] == "&":
|
||||
insideName = True
|
||||
elif value[i] == ';':
|
||||
insideName = False
|
||||
|
||||
if name in self.entityReferences:
|
||||
retval += self.define_entity_reference(name)
|
||||
else:
|
||||
raise NameError("unknown entity ref '" + name + "'")
|
||||
|
||||
name = ""
|
||||
elif insideName:
|
||||
name += value[i]
|
||||
else:
|
||||
retval += value[i]
|
||||
return retval
|
||||
|
||||
def add_instance(self, classGid : Guid, instGid : Guid, classIndex : int, index : int):
|
||||
print("adding instance for class '" + classGid.get_value() + "' with globalid '" + instGid.get_value() + "' [" + str(index) + "]")
|
||||
self._instances.append((classGid.get_value(), instGid.get_value(), classIndex, index))
|
||||
|
||||
# assign relationship `Instance.for Class`
|
||||
self.assign_relationship(instGid, Guid('494D5A6D04BE477B8763E3F57D0DD8C8'), classGid)
|
||||
|
||||
# assign relationship `Class.has Instance`
|
||||
self.assign_relationship(classGid, Guid('7EB41D3C2AE9488483A4E59441BCAEFB'), instGid)
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
import MySQLdb
|
||||
|
||||
from MySQLdb.connections import Connection
|
||||
|
||||
class LibraryOperation:
|
||||
def build_query(self):
|
||||
return ''
|
||||
|
||||
def print_error(self, cur):
|
||||
rows = cur.fetchall()
|
||||
for row in rows:
|
||||
if 'error_description' in row:
|
||||
print (row['error_description'])
|
||||
|
||||
def execute(self, db : Connection):
|
||||
cur = db.cursor()
|
||||
|
||||
query = self.build_query()
|
||||
print(query)
|
||||
cur.execute(query)
|
||||
self.print_error(cur)
|
||||
@ -0,0 +1,5 @@
|
||||
class Normalization:
|
||||
@staticmethod
|
||||
def normalize_uuid(val : str):
|
||||
val = val.replace("{", "").replace("}", "").replace("-", "").strip().lower()
|
||||
return val
|
||||
@ -0,0 +1,47 @@
|
||||
from .core.Guid import Guid
|
||||
from .Normalization import Normalization
|
||||
|
||||
class SQLExpression:
|
||||
|
||||
@staticmethod
|
||||
def sqlescape(parm : str):
|
||||
return parm.replace("'", "\\'")
|
||||
|
||||
@staticmethod
|
||||
def normalize_parm(parm : str):
|
||||
query = ""
|
||||
if parm == None:
|
||||
query += "NULL"
|
||||
elif isinstance(parm, Guid):
|
||||
gid = None
|
||||
if parm is not None:
|
||||
gid = "'" + Normalization.normalize_uuid(parm.get_value()) + "'"
|
||||
else:
|
||||
gid = "NULL"
|
||||
|
||||
query += gid
|
||||
elif isinstance(parm, str):
|
||||
query += "'" + SQLExpression.sqlescape(str(parm)) + "'"
|
||||
else:
|
||||
query += str(parm)
|
||||
|
||||
return query
|
||||
|
||||
@staticmethod
|
||||
def to_string(parm):
|
||||
return SQLExpression.normalize_parm(parm)
|
||||
|
||||
@staticmethod
|
||||
def array_to_string(parms):
|
||||
i = 0
|
||||
query = ''
|
||||
for parm in parms:
|
||||
|
||||
query += SQLExpression.to_string(parm)
|
||||
|
||||
if i < len(parms) - 1:
|
||||
query += ", "
|
||||
|
||||
i += 1
|
||||
|
||||
return query
|
||||
@ -0,0 +1,20 @@
|
||||
from .SQLExpression import SQLExpression
|
||||
|
||||
class SQLFunctionCall (SQLExpression):
|
||||
|
||||
def __init__(self, funcname, parms):
|
||||
self.name = funcname
|
||||
self.parms = parms
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_parameters(self):
|
||||
return self.parms
|
||||
|
||||
def get_parameter_list(self):
|
||||
return SQLExpression.array_to_string(self.parms)
|
||||
|
||||
def __str__(self):
|
||||
return self.get_name() + "(" + self.get_parameter_list() + ")"
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
from .SQLExpression import SQLExpression
|
||||
|
||||
class SQLParameter (SQLExpression):
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def __str__(self):
|
||||
return "@" + self.get_name()
|
||||
@ -0,0 +1,15 @@
|
||||
class Guid:
|
||||
|
||||
def __init__(self, val : str):
|
||||
self.value = val
|
||||
|
||||
def get_value(self) -> str:
|
||||
return self.value
|
||||
|
||||
@staticmethod
|
||||
def create():
|
||||
|
||||
from uuid import uuid4
|
||||
u = uuid4()
|
||||
g = Guid(str(u))
|
||||
return g
|
||||
@ -0,0 +1,18 @@
|
||||
from .Guid import Guid
|
||||
|
||||
"""
|
||||
Represents the Text Attribute `Name`
|
||||
"""
|
||||
IDA_Name = Guid("{9153A637-992E-4712-ADF2-B03F0D9EDEA6}")
|
||||
|
||||
"""
|
||||
Represents the Text Attribute `Value`
|
||||
"""
|
||||
IDA_Value = Guid("{041DD7FD-2D9C-412B-8B9D-D7125C166FE0}")
|
||||
|
||||
"""
|
||||
Represents the Text Attribute `Debug Definition File Name`
|
||||
"""
|
||||
IDA_DebugDefinitionFileName = Guid("{03bf47c7-dc97-43c8-a8c9-c6147bee4e1f}")
|
||||
IDA_DebugDefinitionLineNumber = Guid("{822be9b7-531d-4aa1-818a-6e4de1609057}")
|
||||
IDA_DebugDefinitionColumnNumber = Guid("{0f75c750-e738-4410-9b4e-deb422efc7aa}")
|
||||
@ -0,0 +1,5 @@
|
||||
from .Guid import Guid
|
||||
|
||||
IDC_SourceDefinition = Guid("{5d0b2f03-4886-4ba6-ac3c-8f9612963fa6}")
|
||||
IDC_EntityDefinition = Guid("{15ffa529-6aab-4f1f-8720-f2534951b045}")
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
from .Guid import Guid
|
||||
|
||||
IDR_Instance__has__Source_Definition = Guid("{57cbc351-0428-47e6-a6db-445e4503abab}")
|
||||
@ -0,0 +1,30 @@
|
||||
from .LibraryParser import LibraryParser
|
||||
|
||||
class JSONLibraryParser (LibraryParser):
|
||||
|
||||
def cstyle_strip_comments(self, val):
|
||||
val2 = ""
|
||||
# possible values for comment: 0 = none, 1 = multiline, 2 = singleline
|
||||
comment = 0
|
||||
|
||||
xr = iter(range(0, len(val) - 1))
|
||||
for i in xr:
|
||||
if val[i] == '\n' and comment == 2:
|
||||
comment = 0
|
||||
|
||||
check = val[i:i+2]
|
||||
if check == "/*" and comment == 0:
|
||||
comment = 1
|
||||
next(xr)
|
||||
elif check == "*/" and comment == 1:
|
||||
comment = 0
|
||||
next(xr)
|
||||
elif check == "//":
|
||||
comment = 2
|
||||
next(xr)
|
||||
elif comment == 0:
|
||||
val2 += val[i]
|
||||
|
||||
val2 += val[-1:]
|
||||
return val2
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
class LibraryParser():
|
||||
def __init__(self, manager):
|
||||
|
||||
self.__manager = manager
|
||||
@ -0,0 +1,5 @@
|
||||
class MochaSyntaxError(RuntimeError):
|
||||
def __init__(self, *args):
|
||||
RuntimeError.__init__(self, args)
|
||||
|
||||
pass
|
||||
@ -0,0 +1,46 @@
|
||||
from .LibraryParser import LibraryParser
|
||||
|
||||
from xml.dom import minidom, Node
|
||||
from xml.dom.minidom import Entity
|
||||
|
||||
class XMLLibraryParser(LibraryParser):
|
||||
|
||||
def load_instance(self, xmlnode):
|
||||
print("instance : [" + xmlnode.getAttribute("id") + "]")
|
||||
|
||||
def load_library(self, xmlnode):
|
||||
"""
|
||||
Loads a library from the specified XML node.
|
||||
"""
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
if xmlnode.tagName != "library":
|
||||
return
|
||||
|
||||
id = xmlnode.getAttribute("id")
|
||||
for child in xmlnode.childNodes:
|
||||
if child.tagName == "instances":
|
||||
for child2 in child.childNodes:
|
||||
self.load_library_instance_from_xml(child)
|
||||
|
||||
|
||||
def load_file(self, filename):
|
||||
print("loading xml from " + filename + "... ")
|
||||
|
||||
dom = minidom.getDOMImplementation()
|
||||
dt = dom.createDocumentType("mocha", "-//MBS//DTD Mocha 1.0 Dev//EN", "https://doctype.schemas.alcetech.net/Mocha/1.0/mocha-1.0.dtd")
|
||||
dt.entities.setNamedItem(Entity("IDC_ReturnInstanceSetMethodBinding", "{AADC20F9-7559-429B-AEF0-97E059295C76}", None, None))
|
||||
|
||||
dom = minidom.parse(filename)
|
||||
if (dom.documentElement.tagName != "mocha"):
|
||||
print(filename + ": top-level tag is not 'mocha'")
|
||||
return
|
||||
|
||||
for child in dom.documentElement.childNodes:
|
||||
if child.nodeType == Node.ELEMENT_NODE:
|
||||
if child.tagName == "libraries":
|
||||
for child2 in child.childNodes:
|
||||
self.load_library(child)
|
||||
|
||||
print ("\n")
|
||||
@ -0,0 +1,345 @@
|
||||
from .LibraryParser import LibraryParser
|
||||
from ..core.Guid import Guid
|
||||
from .MochaSyntaxError import MochaSyntaxError
|
||||
|
||||
class YAMLLibraryParser (LibraryParser):
|
||||
|
||||
def __init__(self, manager):
|
||||
LibraryParser.__init__(self, manager)
|
||||
|
||||
self.yamlIds = dict()
|
||||
self.templates = dict()
|
||||
|
||||
# these two are special reserved tagNames
|
||||
# self.yamlIds["entityDefinitions"] = None
|
||||
# self.yamlIds["instance"] = { }
|
||||
|
||||
self.manager = manager
|
||||
self._instances_awaiting_sugar = []
|
||||
|
||||
def apply_sugar(self):
|
||||
print("applying syntactic sugar to remaining instances...")
|
||||
# _instances_also_awaiting_sugar = []
|
||||
|
||||
for inst in self._instances_awaiting_sugar:
|
||||
print("applying sugar from '" + inst["from_file_name"] + "'")
|
||||
self.load_instance(inst)
|
||||
print("\n")
|
||||
|
||||
# do recursively until we're all out of instances awaiting sugar
|
||||
# if len(self._instances_awaiting_sugar) > 0:
|
||||
# self.apply_sugar()
|
||||
|
||||
def load_library(self, elem):
|
||||
print("loading library from elem")
|
||||
|
||||
def load_tenant(self, elem):
|
||||
print("loading tenant from elem")
|
||||
|
||||
def find_custom_tag_name(self, elem) -> (str, Guid):
|
||||
# return tuple (tagname, value)
|
||||
if "instance" in elem:
|
||||
return ("instance", Guid(self.manager.expand_entity_references(elem["instance"])))
|
||||
|
||||
for key in self.yamlIds:
|
||||
if key in elem:
|
||||
k = str(key)
|
||||
v = Guid(self.manager.expand_entity_references(elem[key]))
|
||||
return (k, v)
|
||||
|
||||
return (None, None)
|
||||
|
||||
|
||||
def load_entity_definitions_from_file(self, filename):
|
||||
print("loading entity defs from " + filename)
|
||||
|
||||
import yaml
|
||||
with open(filename, 'r') as file:
|
||||
content = yaml.safe_load_all(file)
|
||||
for doc in content:
|
||||
for elem in doc:
|
||||
if "entityDefinitions" in elem:
|
||||
entities = elem["entityDefinitions"]
|
||||
if not entities is None:
|
||||
for entity in entities:
|
||||
for key in entity:
|
||||
if self.manager.exists_entity_reference(key):
|
||||
print("duplicate entity definition: '" + key + "'")
|
||||
exit(1)
|
||||
|
||||
self.manager.register_entity_reference(key, entity[key], filename)
|
||||
|
||||
def load_instance_with_template(self, elem, template):
|
||||
(parentCreatorKey, parentInstanceId) = self.find_custom_tag_name(template)
|
||||
(creatorKey, instanceId) = self.find_custom_tag_name(elem)
|
||||
|
||||
self.apply_template(elem, template, instanceId)
|
||||
|
||||
def assign_relationship_value(self, instanceId, rel, rel_iid, relationshipValue):
|
||||
if (isinstance(relationshipValue, str)):
|
||||
# single instance, this should be a GUID or entityref
|
||||
# we should only need to refer to existing instance in this case
|
||||
relationshipValueInst = Guid(self.manager.expand_entity_references(relationshipValue))
|
||||
if "instance" in rel:
|
||||
self.manager.assign_relationship(instanceId, Guid(self.manager.expand_entity_references(rel["instance"])), relationshipValueInst)
|
||||
else:
|
||||
print("no relationship instance specified for relationship sugar")
|
||||
|
||||
else:
|
||||
# dynamically created instance
|
||||
#FIXME: this 'instance' isn't always the tag name, this can be subject to customTagName as well!and should be processed accordingly
|
||||
(relinst_key, relinst_iid) = self.find_custom_tag_name(relationshipValue)
|
||||
if relinst_key is not None:
|
||||
# for example, 'relinst_key' is 'elementContent' and 'relinst_iid' is '{8ECA14A4...}'
|
||||
|
||||
if rel_iid is not None:
|
||||
print("found customTagName '" + str(relinst_key) + "' with value '" + str(relinst_iid.get_value()) + "'")
|
||||
|
||||
# relval = Guid(self.manager.expand_entity_references(elem[customTagName]))
|
||||
# we need to create the new instance and assign relationship
|
||||
self.manager.assign_relationship(instanceId, rel_iid, relinst_iid)
|
||||
else:
|
||||
if "globalIdentifier" in relationshipValue:
|
||||
globalIdentifier = Guid(relationshipValue["globalIdentifier"])
|
||||
else:
|
||||
globalIdentifier = Guid.create()
|
||||
|
||||
print("creating new instance for relationship '%s' with globalid '%s'" % (rel_iid, globalIdentifier.get_value()))
|
||||
|
||||
createsInstanceOf = None
|
||||
if "type" in relationshipValue:
|
||||
print("found relationship override type '%s'" % (relationshipValue['type']))
|
||||
createsInstanceOf = Guid(self.manager.expand_entity_references(relationshipValue["type"]))
|
||||
|
||||
elif "customTagNameCreatesInstanceOf" in rel:
|
||||
createsInstanceOf = Guid(self.manager.expand_entity_references(rel["customTagNameCreatesInstanceOf"]))
|
||||
|
||||
if not createsInstanceOf is None:
|
||||
# create the new instance
|
||||
self.manager.add_instance(createsInstanceOf, globalIdentifier, None, None)
|
||||
|
||||
# assign relationships
|
||||
self.manager.assign_relationship(instanceId, rel_iid, globalIdentifier)
|
||||
# self.manager.assign_relationship(globalIdentifier, relationshipInstanceId, instanceId)
|
||||
|
||||
# FIXME: apply relationships from the parent class template
|
||||
|
||||
#? NOTE: You MUST specify 'registerForTemplate: yes' on the template definition for
|
||||
#? sibling relationships to be properly applied!
|
||||
|
||||
if createsInstanceOf.get_value() in self.templates:
|
||||
print("applying template for createsInstanceOf '%s'" % (createsInstanceOf.get_value()))
|
||||
createsInstanceOfTemplate = self.templates[createsInstanceOf.get_value()]
|
||||
self.apply_template(relationshipValue, createsInstanceOfTemplate, globalIdentifier)
|
||||
else:
|
||||
print("no template registered for createsInstanceOf '%s'" % (createsInstanceOf.get_value()))
|
||||
else:
|
||||
print ("neither createsInstanceOf nor override 'type' present for relationship value")
|
||||
|
||||
def apply_template(self, elem, template, instanceId):
|
||||
|
||||
if "value" in elem:
|
||||
print("VALUE found in ELEM:")
|
||||
print(elem["value"])
|
||||
|
||||
if "attributes" in template:
|
||||
attrs = template["attributes"]
|
||||
if isinstance(attrs, list):
|
||||
for attr in attrs:
|
||||
if "customTagName" in attr:
|
||||
customTagName = attr["customTagName"]
|
||||
if customTagName in elem:
|
||||
attrinst = Guid(self.manager.expand_entity_references(attr["instance"]))
|
||||
attrval = elem[customTagName]
|
||||
self.manager.set_attribute_value(instanceId, attrinst, attrval)
|
||||
|
||||
if "relationships" in template:
|
||||
rels = template["relationships"]
|
||||
for rel in rels:
|
||||
if "instance" in rel:
|
||||
rel_iid = rel["instance"] # the globalId of the relationship instance
|
||||
else:
|
||||
print("no relationship instance specified for relationship sugar")
|
||||
continue
|
||||
|
||||
if "customTagName" in rel:
|
||||
customTagName = rel["customTagName"]
|
||||
if customTagName in elem:
|
||||
relationshipValue = elem[customTagName]
|
||||
if relationshipValue is None:
|
||||
continue
|
||||
|
||||
if isinstance(relationshipValue, list):
|
||||
# multiple instances
|
||||
for v in relationshipValue:
|
||||
self.assign_relationship_value(instanceId, rel, Guid(self.manager.expand_entity_references(rel_iid)), v)
|
||||
|
||||
else:
|
||||
self.assign_relationship_value(instanceId, rel, Guid(self.manager.expand_entity_references(rel_iid)), relationshipValue)
|
||||
|
||||
def get_instance_sugar_for_elem(self, elem):
|
||||
if "instance" in elem:
|
||||
return (elem["instance"], "instance", None)
|
||||
else:
|
||||
for key in self.yamlIds:
|
||||
# no 'instance', see if we
|
||||
if key in elem:
|
||||
template = self.yamlIds[key]
|
||||
templateKey = key
|
||||
return (elem[templateKey], templateKey, template)
|
||||
|
||||
return (None, None, None) # should never get here
|
||||
|
||||
|
||||
def load_instance(self, elem, elemParent = None):
|
||||
# 'class' and 'relationship' are both at the 'same level'
|
||||
# so we can't define 'relationship' without first defining 'class'
|
||||
|
||||
# we could try to keep looping as long as we're still getting "unknown tag name"
|
||||
# (instanceID is None), but we could get stuck that way...
|
||||
|
||||
# for now, let's just forward define important classes (e.g. IDC_Relationship)
|
||||
|
||||
|
||||
# all of these problems could be avoided by simply
|
||||
# LOADING EVERYTHING INTO MEMORY (like the .NET version does)
|
||||
# and only committing to the DB at the very end
|
||||
# this will resolve problems where we can't find instances, or use syntactic sugar
|
||||
|
||||
(globalIdentifier, templateKey, template) = self.get_instance_sugar_for_elem(elem)
|
||||
print ("globalIdentifier = " + str(globalIdentifier) + ", templateKey = " + str(templateKey))
|
||||
|
||||
if template is None:
|
||||
# no sugar
|
||||
pass
|
||||
|
||||
customTagName = None
|
||||
if "customTagName" in elem:
|
||||
customTagName = elem["customTagName"]
|
||||
self.yamlIds[customTagName] = elem
|
||||
print("registering customTagName '" + customTagName + "'")
|
||||
|
||||
if "registerForTemplate" in elem:
|
||||
if elem["registerForTemplate"] == True:
|
||||
self.templates[self.manager.expand_entity_references(globalIdentifier)] = elem
|
||||
print("registering elem for template")
|
||||
|
||||
classId = None
|
||||
classIndex = None
|
||||
|
||||
if template is None and elemParent is not None:
|
||||
template = elemParent
|
||||
|
||||
if template is not None:
|
||||
if "instance" in template:
|
||||
classId = Guid(self.manager.expand_entity_references(template["instance"]))
|
||||
else:
|
||||
for key in self.yamlIds:
|
||||
if key in template:
|
||||
classId = Guid(self.manager.expand_entity_references(template[key]))
|
||||
break
|
||||
|
||||
if "index" in template:
|
||||
classIndex = template["index"]
|
||||
|
||||
instanceId = None
|
||||
creatorKey = None
|
||||
if "instance" in elem:
|
||||
if "templateOnly" in elem and elem["templateOnly"] == True:
|
||||
# instanceId = None
|
||||
instanceId = Guid(self.manager.expand_entity_references(elem["instance"]))
|
||||
else:
|
||||
instanceId = Guid(self.manager.expand_entity_references(elem["instance"]))
|
||||
|
||||
creatorKey = 'instance'
|
||||
else:
|
||||
for key in self.yamlIds:
|
||||
if key in elem:
|
||||
instanceId = Guid(self.manager.expand_entity_references(elem[key]))
|
||||
creatorKey = key
|
||||
break
|
||||
|
||||
index = None
|
||||
if "index" in elem:
|
||||
index = elem["index"]
|
||||
# else:
|
||||
# print("index not found for element")
|
||||
# print(elem)
|
||||
|
||||
if classId is None and instanceId is not None:
|
||||
#!!! HACK HACK HACK !!!
|
||||
classId = instanceId
|
||||
if classIndex is None and index is None:
|
||||
classIndex = 1
|
||||
index = 1
|
||||
print("WARNING: class hack used for instanceId " + instanceId.get_value() + " ( index " + str(classIndex) + "$" + str(index) + ")")
|
||||
|
||||
if instanceId is not None:
|
||||
self.manager.add_instance(classId, instanceId, classIndex, index)
|
||||
|
||||
if creatorKey == 'class': #FIXME: remove this special-case behavior
|
||||
print("creating class " + instanceId.get_value())
|
||||
|
||||
# # assign relationship `Instance.for Class`
|
||||
# self.manager.assign_relationship(instanceId, Guid('494D5A6D04BE477B8763E3F57D0DD8C8'), Guid('B9C9B9B7AD8A4CBDAA6BE05784630B6B'))
|
||||
|
||||
# # assign relationship `Class.has Instance`
|
||||
# self.manager.assign_relationship(Guid('B9C9B9B7AD8A4CBDAA6BE05784630B6B'), Guid('7EB41D3C2AE9488483A4E59441BCAEFB'), instanceId)
|
||||
|
||||
if "instances" in elem:
|
||||
classInsts = elem["instances"]
|
||||
for inst in classInsts:
|
||||
self.load_instance(inst, elem)
|
||||
|
||||
else:
|
||||
print("creating instance " + instanceId.get_value() + " (of class " + classId.get_value() + ")")
|
||||
|
||||
# # assign relationship `Instance.for Class`
|
||||
# self.manager.assign_relationship(instanceId, Guid('494D5A6D04BE477B8763E3F57D0DD8C8'), classId)
|
||||
|
||||
# # assign relationship `Class.has Instance`
|
||||
# self.manager.assign_relationship(classId, Guid('7EB41D3C2AE9488483A4E59441BCAEFB'), instanceId)
|
||||
|
||||
# self.manager.create_instance_of(classId, instanceId, classIndex, index)
|
||||
|
||||
if templateKey is not None:
|
||||
if template is not None:
|
||||
print("using template (" + templateKey + ")")
|
||||
#print(template)
|
||||
|
||||
self.load_instance_with_template(elem, template)
|
||||
else:
|
||||
#print("ignoring '" + templateKey + "'")
|
||||
pass
|
||||
|
||||
def load_instances_from_file(self, filename):
|
||||
print("loading instances from " + filename)
|
||||
|
||||
import yaml
|
||||
with open(filename, 'r') as file:
|
||||
content = yaml.safe_load_all(file)
|
||||
for doc in content:
|
||||
for elem in doc:
|
||||
if "entityDefinitions" in elem:
|
||||
continue
|
||||
elif "library" in elem:
|
||||
self.load_library(filename, elem)
|
||||
elif "tenant" in elem:
|
||||
self.load_tenant(filename, elem)
|
||||
else:
|
||||
raise MochaSyntaxError("neither 'library' nor 'tenant' top level element found")
|
||||
|
||||
def load_library(self, filename, elem):
|
||||
if "instances" in elem:
|
||||
instances = elem["instances"]
|
||||
for elem1 in instances:
|
||||
if "instance" in elem1:
|
||||
# this is an instance definition (no sugar), so just load it
|
||||
self.load_instance(elem1)
|
||||
else:
|
||||
# this is a syntactic sugar definition, so store it for later use
|
||||
elem1["from_file_name"] = filename
|
||||
self._instances_awaiting_sugar.append(elem1)
|
||||
|
||||
def load_tenant(self, filename, elem):
|
||||
pass
|
||||
@ -0,0 +1,4 @@
|
||||
from .LibraryParser import LibraryParser
|
||||
from .JSONLibraryParser import JSONLibraryParser
|
||||
from .XMLLibraryParser import XMLLibraryParser
|
||||
from .YAMLLibraryParser import YAMLLibraryParser
|
||||
@ -0,0 +1,21 @@
|
||||
from .StoredProcedureOperation import StoredProcedureOperation
|
||||
from ..core.Guid import Guid
|
||||
from ..SQLParameter import SQLParameter
|
||||
from ..SQLFunctionCall import SQLFunctionCall
|
||||
|
||||
class AssignAttributeOperation(StoredProcedureOperation):
|
||||
|
||||
def __init__(self, instanceId : Guid, attributeInstanceId : Guid, value):
|
||||
self.instanceId = instanceId
|
||||
self.attributeInstanceId = attributeInstanceId
|
||||
self.value = value
|
||||
|
||||
def get_sp_name(self):
|
||||
return "mocha_set_attribute_value"
|
||||
|
||||
def get_sp_parameters(self):
|
||||
return [ SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.instanceId ]), SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.attributeInstanceId ]), str(self.value), None, None ]
|
||||
#query = "CALL mocha_set_attribute_value(mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + instanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + attributeInstanceId.get_value() + "')), '" + str(value) + "', NULL, NULL);"
|
||||
#print(query)
|
||||
#cur.execute(query)
|
||||
#self.print_error(cur)
|
||||
@ -0,0 +1,21 @@
|
||||
from .StoredProcedureOperation import StoredProcedureOperation
|
||||
from ..core.Guid import Guid
|
||||
from ..SQLParameter import SQLParameter
|
||||
from ..SQLFunctionCall import SQLFunctionCall
|
||||
|
||||
class AssignRelationshipOperation(StoredProcedureOperation):
|
||||
|
||||
def __init__(self, instanceId : Guid, relationshipInstanceId : Guid, targetInstanceId : Guid):
|
||||
self.instanceId = instanceId
|
||||
self.relationshipInstanceId = relationshipInstanceId
|
||||
self.targetInstanceId = targetInstanceId
|
||||
|
||||
def get_sp_name(self):
|
||||
return "mocha_assign_relationship"
|
||||
|
||||
def get_sp_parameters(self):
|
||||
return [ SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.instanceId ]), SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.relationshipInstanceId ]), SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.targetInstanceId ]), None, None ]
|
||||
#query = "CALL mocha_set_attribute_value(mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + instanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + attributeInstanceId.get_value() + "')), '" + str(value) + "', NULL, NULL);"
|
||||
#print(query)
|
||||
#cur.execute(query)
|
||||
#self.print_error(cur)
|
||||
@ -0,0 +1,17 @@
|
||||
from .StoredProcedureOperation import StoredProcedureOperation
|
||||
from ..SQLParameter import SQLParameter
|
||||
from ..SQLFunctionCall import SQLFunctionCall
|
||||
from ..core.Guid import Guid
|
||||
|
||||
class CreateClassOperation (StoredProcedureOperation):
|
||||
|
||||
def __init__(self, globalIdentifier : Guid, classIndex : int):
|
||||
self.globalIdentifier = globalIdentifier
|
||||
self.classIndex = classIndex
|
||||
|
||||
def get_sp_name(self):
|
||||
return 'mocha_create_class'
|
||||
|
||||
def get_sp_parameters(self):
|
||||
return [ self.classIndex, self.globalIdentifier, None, None, SQLParameter("dummy") ]
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
from .StoredProcedureOperation import StoredProcedureOperation
|
||||
from ..core.Guid import Guid
|
||||
from ..SQLParameter import SQLParameter
|
||||
from ..SQLFunctionCall import SQLFunctionCall
|
||||
|
||||
class CreateInstanceOperation(StoredProcedureOperation):
|
||||
|
||||
def __init__(self, globalIdentifier : Guid, classIndex : int, instanceIndex : int):
|
||||
self.globalIdentifier = globalIdentifier
|
||||
self.classIndex = classIndex
|
||||
self.instanceIndex = instanceIndex
|
||||
|
||||
def get_sp_name(self):
|
||||
return 'mocha_create_instance'
|
||||
|
||||
def get_sp_parameters(self):
|
||||
return [ self.globalIdentifier, self.classIndex, self.instanceIndex, None, None, SQLParameter('assigned_inst_id') ]
|
||||
@ -0,0 +1,36 @@
|
||||
from .StoredProcedureOperation import StoredProcedureOperation
|
||||
from ..core.Guid import Guid
|
||||
from ..SQLParameter import SQLParameter
|
||||
from ..SQLFunctionCall import SQLFunctionCall
|
||||
|
||||
class PrepareInstanceOperation(StoredProcedureOperation):
|
||||
|
||||
def __init__(self, classGlobalIdentifier : Guid, globalIdentifier : Guid, classIndex : int, instanceIndex : int):
|
||||
self.classGlobalIdentifier = classGlobalIdentifier
|
||||
self.globalIdentifier = globalIdentifier
|
||||
self.classIndex = classIndex
|
||||
self.instanceIndex = instanceIndex
|
||||
|
||||
def get_sp_name(self):
|
||||
return "mocha_prepare_instance"
|
||||
|
||||
def get_sp_parameters(self):
|
||||
parms = []
|
||||
|
||||
globalId = None
|
||||
if self.globalIdentifier is not None:
|
||||
globalId = self.globalIdentifier
|
||||
|
||||
classGlobalId = None
|
||||
if self.classGlobalIdentifier is not None:
|
||||
classGlobalId = self.classGlobalIdentifier
|
||||
|
||||
strCid = None
|
||||
if self.classIndex is not None:
|
||||
strCid = self.classIndex
|
||||
|
||||
strIid = None
|
||||
if self.instanceIndex is not None:
|
||||
strIid = self.instanceIndex
|
||||
|
||||
return [strCid, strIid, classGlobalId, globalId, None, None, SQLParameter("p_assigned_inst_id")]
|
||||
@ -0,0 +1,24 @@
|
||||
import MySQLdb
|
||||
|
||||
from ..LibraryOperation import LibraryOperation
|
||||
from MySQLdb.connections import Connection
|
||||
from ..SQLExpression import SQLExpression
|
||||
from ..SQLParameter import SQLParameter
|
||||
from ..SQLFunctionCall import SQLFunctionCall
|
||||
from ..core.Guid import Guid
|
||||
|
||||
class StoredProcedureOperation (LibraryOperation):
|
||||
def get_sp_name(self):
|
||||
return ''
|
||||
|
||||
def get_sp_parameters(self):
|
||||
return []
|
||||
|
||||
def build_query(self):
|
||||
query = "CALL " + self.get_sp_name() + "("
|
||||
parms = self.get_sp_parameters()
|
||||
query += SQLExpression.array_to_string(parms)
|
||||
|
||||
query += ")"
|
||||
return query
|
||||
|
||||
46
mocha-suv/common/libexec/internal/mocha-install-library.py
Normal file
46
mocha-suv/common/libexec/internal/mocha-install-library.py
Normal file
@ -0,0 +1,46 @@
|
||||
import os, sys
|
||||
|
||||
from librarymanager.LibraryManager import MochaLibraryManager
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
mlm = MochaLibraryManager()
|
||||
path = None
|
||||
dbname = None
|
||||
dbuser = None
|
||||
dbpass = None
|
||||
tenantName = 'super'
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
path = sys.argv[1]
|
||||
print("installing mocha from path: " + path)
|
||||
|
||||
elif len(sys.argv) == 5:
|
||||
path = sys.argv[4]
|
||||
dbname = sys.argv[1]
|
||||
dbuser = sys.argv[2]
|
||||
dbpass = sys.argv[3]
|
||||
print("installing mocha from path: " + path)
|
||||
print("using dbname = " + dbname + ", dbuser = " + dbuser)
|
||||
|
||||
elif len(sys.argv) == 6:
|
||||
tenantName = sys.argv[1]
|
||||
path = sys.argv[5]
|
||||
dbname = sys.argv[2]
|
||||
dbuser = sys.argv[3]
|
||||
dbpass = sys.argv[4]
|
||||
print("installing mocha from path: " + path)
|
||||
print("using dbname = " + dbname + ", dbuser = " + dbuser)
|
||||
|
||||
else:
|
||||
print("usage: mocha-install-library TENANTNAME [DATABASENAME USERNAME PASSWORD] PATH_TO_LIBRARY")
|
||||
exit(3)
|
||||
|
||||
mlm.connect('localhost', dbname, dbuser, dbpass)
|
||||
mlm.select_tenant(tenantName)
|
||||
result = mlm.install_from_path(path)
|
||||
|
||||
if result:
|
||||
mlm.commit()
|
||||
|
||||
mlm.close()
|
||||
34
mocha-suv/common/libexec/internal/mocha-lib.py
Normal file
34
mocha-suv/common/libexec/internal/mocha-lib.py
Normal file
@ -0,0 +1,34 @@
|
||||
import os
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
def zipdir(path, ziph):
|
||||
# ziph is zipfile handle
|
||||
for root, dirs, files in os.walk(path):
|
||||
for file in files:
|
||||
if file.endswith(".xml") or file == "manifest.inf":
|
||||
ziph.write(os.path.join(root, file),
|
||||
os.path.relpath(os.path.join(root, file),
|
||||
os.path.join(path, '..')))
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv[1] == "build":
|
||||
if len(sys.argv) > 2:
|
||||
|
||||
# usage: mocha lib build (folder) (filename.zip)
|
||||
if len(sys.argv) > 3:
|
||||
|
||||
with zipfile.ZipFile(sys.argv[3], 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
zipdir(sys.argv[2], zipf)
|
||||
|
||||
else:
|
||||
|
||||
print ("usage: mocha lib build FILENAME")
|
||||
|
||||
else:
|
||||
|
||||
print ("usage: mocha lib build")
|
||||
|
||||
else:
|
||||
|
||||
print ("usage: mocha lib build")
|
||||
21
mocha-suv/common/libexec/mocha
Normal file
21
mocha-suv/common/libexec/mocha
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
|
||||
if [ -f "/usr/lib/mocha/mocha-$1" ]; then
|
||||
|
||||
MOCHA_COMMAND=$1
|
||||
shift
|
||||
exec "/usr/lib/mocha/mocha-$MOCHA_COMMAND" ${1+"$@"}
|
||||
|
||||
else
|
||||
|
||||
echo "mocha: '$1' is not a mocha command. See 'mocha --help'."
|
||||
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
echo "usage: mocha $(echo /usr/lib/mocha/mocha-* | sed -e 's/\/usr\/lib\/mocha\/mocha\-//g' -e 's/ /|/g')"
|
||||
|
||||
fi
|
||||
19
mocha-suv/common/libexec/mocha-clean
Normal file
19
mocha-suv/common/libexec/mocha-clean
Normal file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$1" != "-y" ]; then
|
||||
|
||||
echo "ARE YOU SURE you wish to CLEAN this SUV?"
|
||||
echo "This will DESTROY all data and rebuild from a clean master image."
|
||||
echo ""
|
||||
echo -n "Type YES to confirm: > "
|
||||
read CONFIRMYES
|
||||
if [ "$CONFIRMYES" != "YES" ]; then
|
||||
echo ""
|
||||
echo "OK, not doing anything"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
rm /etc/mocha/*
|
||||
mocha up
|
||||
3
mocha-suv/common/libexec/mocha-lib
Executable file
3
mocha-suv/common/libexec/mocha-lib
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/bin/python3 mocha-lib.py ${1+"$@"}
|
||||
363
mocha-suv/common/libexec/mocha-oms
Executable file
363
mocha-suv/common/libexec/mocha-oms
Executable file
@ -0,0 +1,363 @@
|
||||
#!/bin/bash
|
||||
|
||||
MOCHA_DBNAME=$(cat /etc/mocha/dbname)
|
||||
MOCHA_DBUSER=$(cat /etc/mocha/dbuser)
|
||||
MOCHA_DBPASS=$(cat /etc/mocha/dbpass)
|
||||
|
||||
MOCHA_MYSQL="mysql -D $MOCHA_DBNAME -u $MOCHA_DBUSER --password=$MOCHA_DBPASS"
|
||||
|
||||
if [ ! -d ~/.config ]; then
|
||||
mkdir ~/.config
|
||||
fi
|
||||
if [ ! -d ~/.config/mocha ]; then
|
||||
mkdir ~/.config/mocha
|
||||
fi
|
||||
|
||||
if [ -f ~/.config/mocha/tenant ]; then
|
||||
|
||||
CURRENT_TENANT=$(cat ~/.config/mocha/tenant)
|
||||
#echo "current tenant: $CURRENT_TENANT"
|
||||
#echo "use 'mocha oms tenant select' to change"
|
||||
|
||||
fi
|
||||
|
||||
if [ "$1" == "install" ]; then
|
||||
|
||||
if [ "$2" == "library" ]; then
|
||||
echo "installing Mocha OMS from library '$3'..."
|
||||
|
||||
python3 /usr/lib/mocha/internal/mocha-install-library.py $CURRENT_TENANT $MOCHA_DBNAME $MOCHA_DBUSER $MOCHA_DBPASS $3
|
||||
|
||||
else
|
||||
echo "installing Mocha OMS from SQL..."
|
||||
|
||||
cd /usr/lib/mocha/sql/php
|
||||
php ./install_mysql.php $MOCHA_DBNAME $MOCHA_DBUSER $MOCHA_DBPASS
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(1);" -e "CALL mocha_build_tenant_from_template(mocha_get_current_tenant(), 1);" -e "CALL mocha_release_tenant();"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$1" == "tenant" ]; then
|
||||
|
||||
if [ "$2" == "list" ]; then
|
||||
|
||||
if [ "$3" == "names" ]; then
|
||||
|
||||
$MOCHA_MYSQL -N -s -e "SELECT tenant_name FROM mocha_tenants"
|
||||
|
||||
else
|
||||
|
||||
$MOCHA_MYSQL -e "SELECT * FROM mocha_tenants"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$2" == "create" ]; then
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
|
||||
echo "usage: mocha oms tenant create TENANTNAME"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_create_tenant('$3', NULL)"
|
||||
$MOCHA_MYSQL -e "CALL mocha_build_tenant_from_template(mocha_get_tenant_by_name('$3'), 1);"
|
||||
|
||||
OLDTENANT=$(mocha oms tenant)
|
||||
mocha oms tenant select $3
|
||||
mocha oms install library /usr/share/mocha/libraries/
|
||||
mocha oms tenant select $OLDTENANT
|
||||
|
||||
|
||||
elif [ "$2" == "delete" ]; then
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
|
||||
echo "usage: mocha oms tenant delete TENANTNAME"
|
||||
|
||||
fi
|
||||
|
||||
if [ "$3" == "super" ]; then
|
||||
|
||||
echo "cannot delete the super tenant!"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
$MOCHA_MYSQL -e "DELETE FROM mocha_tenants WHERE tenant_name = '$3'"
|
||||
|
||||
elif [ "$2" == "select" ]; then
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
|
||||
echo "usage: mocha oms tenant select TENANTNAME"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
echo $3 > ~/.config/mocha/tenant
|
||||
echo "current tenant: $3"
|
||||
|
||||
elif [ "$2" == "release" ]; then
|
||||
|
||||
rm ~/.config/mocha/tenant
|
||||
echo "current tenant: (none)"
|
||||
|
||||
elif [ "$2" == "" ]; then
|
||||
|
||||
if [ -f ~/.config/mocha/tenant ]; then
|
||||
echo $(cat ~/.config/mocha/tenant)
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$1" == "user" ]; then
|
||||
|
||||
if [ "$CURRENT_TENANT" == "" ]; then
|
||||
|
||||
echo "no tenant selected; please 'mocha oms tenant select' first"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
if [ "$2" == "list" ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "SELECT * FROM mocha_instances WHERE class_id = 39 AND tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT')";
|
||||
|
||||
elif [ "$2" == "add" ]; then
|
||||
|
||||
if [ "$3" != "" ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "CALL mocha_create_user('$3', NULL);" -e "CALL mocha_release_tenant();"
|
||||
echo $3
|
||||
|
||||
else
|
||||
|
||||
echo "usage: mocha oms user add USERNAME"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$2" == "set-password" ]; then
|
||||
|
||||
if [ "$3" == "" ]; then
|
||||
|
||||
echo "usage: mocha oms user set-password USERNAME [PASSWORD]"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
PASSWORD=$4
|
||||
if [ "$PASSWORD" == "" ]; then
|
||||
|
||||
echo "Changing password for $3."
|
||||
|
||||
stty -echo
|
||||
read -p "New password: " PASSWORD
|
||||
stty echo
|
||||
echo ""
|
||||
|
||||
stty -echo
|
||||
read -p "Retype new password: " PASSWORD2
|
||||
stty echo
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
if [ "$PASSWORD" != "$PASSWORD2" ]; then
|
||||
echo "Sorry, passwords do not match."
|
||||
exit
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
PASSWORD_SALT=$(pwgen -s 128 -N 1)
|
||||
PASSWORD_SALTED=$PASSWORD$PASSWORD_SALT
|
||||
PASSWORD_HASH=$(php /usr/lib/mocha/sql/php/hash_pw.php $PASSWORD_SALTED)
|
||||
|
||||
# these two commands SHOULD execute atomically
|
||||
# BUT for some reason this doesn't work on initial provisioning of the vagrant vm
|
||||
# ........ for some reason, it works just fine when run manually though...
|
||||
# oh well, it's not like anything is going to happen in the few picoseconds between calls...
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "CALL mocha_set_attribute_value(mocha_get_user_by_username('$3'), mocha_get_instance_by_global_identifier('F377FC294DF14AFB96434191F37A00A9'), '$PASSWORD_HASH', NULL, NULL);" -e "CALL mocha_set_attribute_value(mocha_get_user_by_username('$3'), mocha_get_instance_by_global_identifier('8C5A99BC40ED4FA2B23FF373C1F3F4BE'), '$PASSWORD_SALT', NULL, NULL);" -e "CALL mocha_release_tenant();"
|
||||
if [ $? -ne 0 ]; then
|
||||
|
||||
echo "mocha: password unchanged"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
echo "mocha: password updated successfully"
|
||||
exit
|
||||
|
||||
else
|
||||
|
||||
echo "usage: mocha oms user add|delete|lock|list|unlock|set-password"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
elif [ "$1" == "instance" ]; then
|
||||
|
||||
if [ "$2" == "list" ]; then
|
||||
|
||||
# usage: mocha oms instance list attributes INSTID
|
||||
if [ "$3" == "" ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "SELECT id, tenant_id, CONCAT(class_id, '$', inst_id) AS inst_key, global_identifier FROM mocha_instances WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT')"
|
||||
|
||||
elif [ "$3" == "attributes" ]; then
|
||||
|
||||
if [ "$4" == "" ]; then
|
||||
|
||||
echo "usage: mocha oms instance list attributes INSTID"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
# thanks https://stackoverflow.com/a/10520718
|
||||
ATT_INST_ID=$4
|
||||
ATT_INST_ID_CID=${ATT_INST_ID%\$*}
|
||||
ATT_INST_ID_IID=${ATT_INST_ID#*\$}
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "SELECT * FROM mocha_attributes WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND src_inst_id = mocha_get_instance_by_key($ATT_INST_ID_CID, $ATT_INST_ID_IID);" -e "CALL mocha_release_tenant();"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$2" == "get" ]; then
|
||||
|
||||
if [ "$3" == "by-gid" ]; then
|
||||
|
||||
# thanks https://stackoverflow.com/a/911213
|
||||
if [ -t 1 ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "SELECT * FROM mocha_instances WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND global_identifier = mocha_normalize_uuid('$4');"
|
||||
|
||||
else
|
||||
|
||||
$MOCHA_MYSQL -N -e "SELECT id FROM mocha_instances WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND global_identifier = mocha_normalize_uuid('$4');"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$3" == "by-iid" ]; then
|
||||
|
||||
# thanks https://stackoverflow.com/a/10520718
|
||||
INST_ID=$4
|
||||
INST_ID_CID=${INST_ID%\$*}
|
||||
INST_ID_IID=${INST_ID#*\$}
|
||||
|
||||
# thanks https://stackoverflow.com/a/911213
|
||||
if [ -t 1 ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "SELECT * FROM mocha_instances WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND class_id = $INST_ID_CID AND inst_id = $INST_ID_IID;" -e "CALL mocha_release_tenant();"
|
||||
|
||||
else
|
||||
|
||||
$MOCHA_MYSQL -N -e "SELECT id FROM mocha_instances WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND class_id = $INST_ID_CID AND inst_id = $INST_ID_IID;"
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
elif [ "$1" == "attribute" ]; then
|
||||
|
||||
if [ "$2" == "list" ]; then
|
||||
|
||||
REL_COLUMNS="id, tenant_id, mocha_get_instance_key(src_inst_id) AS source_inst, mocha_get_instance_key(att_inst_id) AS attribute_inst, att_value, mocha_get_instance_key(usr_inst_id) AS user_inst, att_effective_date"
|
||||
|
||||
# usage: mocha oms instance list attributes INSTID
|
||||
if [ "$3" == "" ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "SELECT $REL_COLUMNS FROM mocha_attributes WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT');" -e "CALL mocha_release_tenant();"
|
||||
|
||||
elif [ "$3" == "for" ]; then
|
||||
|
||||
if [ "$4" == "" ]; then
|
||||
|
||||
echo "usage: mocha oms relationship list for INSTID"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "SELECT $REL_COLUMNS FROM mocha_attributes WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND src_inst_id = $4;" -e "CALL mocha_release_tenant();"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$2" == "get" ]; then
|
||||
|
||||
if [ "$4" == "for" ]; then
|
||||
|
||||
ATT_ID=$3
|
||||
INST_ID=$5
|
||||
|
||||
$MOCHA_MYSQL -N -s -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "CALL mocha_get_attribute_value($INST_ID, $ATT_ID, NULL);" -e "CALL mocha_release_tenant();"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$2" == "set" ]; then
|
||||
|
||||
if [ "$4" == "for" ]; then
|
||||
|
||||
# usage: `mocha oms attribute set (att) for (inst) (value)`
|
||||
|
||||
ATT_ID=$3
|
||||
INST_ID=$5
|
||||
ATT_VALUE=$6
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "CALL mocha_set_attribute_value($INST_ID, $ATT_ID, '$ATT_VALUE', NULL, NULL);" -e "CALL mocha_release_tenant();"
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
elif [ "$1" == "relationship" ]; then
|
||||
|
||||
if [ "$2" == "list" ]; then
|
||||
|
||||
REL_COLUMNS="id, tenant_id, mocha_get_instance_key(source_inst_id) AS source_inst, mocha_get_instance_key(relationship_inst_id) AS relationship_inst, mocha_get_instance_key(destination_inst_id) AS destination_inst, mocha_get_instance_key(user_inst_id) AS user_inst, effective_date"
|
||||
|
||||
# usage: mocha oms instance list attributes INSTID
|
||||
if [ "$3" == "" ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "SELECT $REL_COLUMNS FROM mocha_relationships WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT')"
|
||||
|
||||
elif [ "$3" == "for" ]; then
|
||||
|
||||
if [ "$4" == "" ]; then
|
||||
|
||||
echo "usage: mocha oms relationship list for INSTID"
|
||||
exit
|
||||
|
||||
fi
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "SELECT $REL_COLUMNS FROM mocha_relationships WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND source_inst_id = $4;" -e "CALL mocha_release_tenant();"
|
||||
|
||||
fi
|
||||
|
||||
elif [ "$2" == "get" ]; then
|
||||
|
||||
if [ "$3" == "by-gid" ]; then
|
||||
|
||||
# thanks https://stackoverflow.com/a/911213
|
||||
if [ -t 1 ]; then
|
||||
|
||||
$MOCHA_MYSQL -e "CALL mocha_select_tenant(mocha_get_tenant_by_name('$CURRENT_TENANT'));" -e "SELECT * FROM mocha_instances WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND global_identifier = mocha_normalize_uuid('$4');" -e "CALL mocha_release_tenant();"
|
||||
|
||||
else
|
||||
|
||||
$MOCHA_MYSQL -N -e "SELECT id FROM mocha_instances WHERE tenant_id = mocha_get_tenant_by_name('$CURRENT_TENANT') AND global_identifier = mocha_normalize_uuid('$4');"
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
echo "usage: mocha oms tenant|user|instance|attribute|relationship"
|
||||
|
||||
fi
|
||||
|
||||
92
mocha-suv/common/libexec/mocha-suv
Executable file
92
mocha-suv/common/libexec/mocha-suv
Executable file
@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
|
||||
# mocha suv list
|
||||
# mocha suv up
|
||||
# mocha suv down
|
||||
# mocha suv new
|
||||
|
||||
VAGRANT_MOCHADIR=/home/beckermj/Documents/Vagrant/mocha
|
||||
VAGRANT_MACHINESDIR=$VAGRANT_MOCHADIR/machines
|
||||
|
||||
if [ "$1" == "list" ]; then
|
||||
|
||||
ls $VAGRANT_MACHINESDIR
|
||||
|
||||
elif [ "$1" == "up" ]; then
|
||||
|
||||
if [ "$2" != "" ]; then
|
||||
MACHINEPATH=$VAGRANT_MACHINESDIR/$2
|
||||
if [ -d "$MACHINEPATH" ]; then
|
||||
cd $MACHINEPATH
|
||||
vagrant up
|
||||
else
|
||||
echo "unknown machine named $2"
|
||||
fi
|
||||
else
|
||||
echo "usage: mocha suv up MACHINENAME"
|
||||
fi
|
||||
|
||||
elif [ "$1" == "down" ]; then
|
||||
|
||||
if [ "$2" != "" ]; then
|
||||
|
||||
MACHINEPATH=$VAGRANT_MACHINESDIR/$2
|
||||
if [ -d "$MACHINEPATH" ]; then
|
||||
cd $MACHINEPATH
|
||||
vagrant halt
|
||||
else
|
||||
echo "unknown machine named $2"
|
||||
fi
|
||||
|
||||
else
|
||||
echo "usage: mocha suv down MACHINENAME"
|
||||
fi
|
||||
|
||||
elif [ "$1" == "shell" ]; then
|
||||
|
||||
if [ "$2" != "" ]; then
|
||||
|
||||
MACHINEPATH=$VAGRANT_MACHINESDIR/$2
|
||||
if [ -d "$MACHINEPATH" ]; then
|
||||
cd $MACHINEPATH
|
||||
vagrant ssh
|
||||
else
|
||||
echo "unknown machine named $2"
|
||||
fi
|
||||
else
|
||||
echo "usage: mocha suv shell MACHINENAME"
|
||||
fi
|
||||
|
||||
elif [ "$1" == "delete" ]; then
|
||||
|
||||
if [ "$2" != "" ]; then
|
||||
|
||||
MACHINEPATH=$VAGRANT_MACHINESDIR/$2
|
||||
if [ -d "$MACHINEPATH" ]; then
|
||||
cd $MACHINEPATH
|
||||
vagrant destroy
|
||||
if [ "$?" == "0" ]; then
|
||||
rm -rf $MACHINEPATH
|
||||
fi
|
||||
else
|
||||
echo "unknown machine named $2"
|
||||
fi
|
||||
else
|
||||
echo "usage: mocha suv delete MACHINENAME"
|
||||
fi
|
||||
|
||||
elif [ "$1" == "new" ]; then
|
||||
|
||||
cd $VAGRANT_MOCHADIR
|
||||
|
||||
if [ "$2" == "--transient" ]; then
|
||||
./provision --transient
|
||||
else
|
||||
./provision
|
||||
fi
|
||||
|
||||
else
|
||||
echo "usage: mocha suv new [--transient] | (up|down|shell|delete MACHINENAME) | list"
|
||||
|
||||
fi
|
||||
|
||||
86
mocha-suv/common/libexec/mocha-up
Executable file
86
mocha-suv/common/libexec/mocha-up
Executable file
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
|
||||
FIRSTRUN=0
|
||||
if [ -f "/etc/mocha/username" ]; then
|
||||
MOCHA_USERNAME=$(cat /etc/mocha/username)
|
||||
MOCHA_PASSWORD=$(cat /etc/mocha/userpass)
|
||||
else
|
||||
# we are running for the first time (or we are transient)
|
||||
HTML_HOME=/var/www/html
|
||||
|
||||
# reset the configuration file
|
||||
cp /etc/mocha/include/Configuration.inc.php.template $HTML_HOME/include/Configuration.inc.php
|
||||
|
||||
# generate a not-very-secure but easily-rememberable password for zq-developer
|
||||
MOCHA_USERNAME="zq-developer"
|
||||
MOCHA_PASSWORD=$(pwgen -N 1)
|
||||
|
||||
if [ ! $? -eq 0 ]; then
|
||||
echo ""
|
||||
echo "could not generate a secure password, you may need to (re-)install pwgen"
|
||||
echo ""
|
||||
exit 3
|
||||
fi
|
||||
|
||||
echo $MOCHA_USERNAME > /etc/mocha/username
|
||||
echo $MOCHA_PASSWORD > /etc/mocha/userpass
|
||||
|
||||
MOCHA_DB_DATABASENAME="mocha_suv"
|
||||
MOCHA_DB_USERNAME="mocha_suv"
|
||||
|
||||
# also generate a slightly more secure machine password for the mariadb database...
|
||||
MOCHA_DB_PASSWORD=$(pwgen -s 32 -N 1)
|
||||
# ... and add it to the configuration file
|
||||
sed -i -e "s/@@MOCHA_DB_DATABASENAME@@/$MOCHA_DB_DATABASENAME/" -e "s/@@MOCHA_DB_USERNAME@@/$MOCHA_DB_USERNAME/" -e "s/@@MOCHA_DB_PASSWORD@@/$MOCHA_DB_PASSWORD/" $HTML_HOME/include/Configuration.inc.php
|
||||
|
||||
# ... and also add it to our local configuration
|
||||
echo $MOCHA_DB_DATABASENAME > /etc/mocha/dbname
|
||||
echo $MOCHA_DB_USERNAME > /etc/mocha/dbuser
|
||||
echo $MOCHA_DB_PASSWORD > /etc/mocha/dbpass
|
||||
|
||||
# don't forget to make a backup
|
||||
cp $HTML_HOME/include/Configuration.inc.php $HTML_HOME/include/Configuration.inc.php.bak
|
||||
|
||||
# create the MySQL database and user with the previously generated password
|
||||
mysql -e "DROP DATABASE IF EXISTS $MOCHA_DB_DATABASENAME; DROP USER IF EXISTS $MOCHA_DB_USERNAME;"
|
||||
mysql -e "CREATE DATABASE $MOCHA_DB_DATABASENAME; CREATE USER $MOCHA_DB_USERNAME IDENTIFIED BY '$MOCHA_DB_PASSWORD'; GRANT ALL ON $MOCHA_DB_DATABASENAME.* TO '$MOCHA_DB_USERNAME'@'%';"
|
||||
|
||||
# install mocha using the `mocha oms` command
|
||||
mocha oms install
|
||||
mocha oms install library /usr/share/mocha/libraries
|
||||
|
||||
mocha oms tenant select super
|
||||
|
||||
# set the new user name and password for the initial mocha user
|
||||
mocha oms user set-password "$MOCHA_USERNAME" "$MOCHA_PASSWORD"
|
||||
|
||||
mocha oms tenant release
|
||||
|
||||
# record the initial start time for the SUV
|
||||
echo $(date "+%Y-%m-%dT%H:%M:%S") > /etc/mocha/suvstart
|
||||
chmod a+r /etc/mocha/suvstart
|
||||
|
||||
FIRSTRUN=1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "******************************************"
|
||||
echo ""
|
||||
echo "Thank you for provisioning your Mocha SUV!"
|
||||
echo "You can log in with the following details:"
|
||||
echo ""
|
||||
echo "User name: $MOCHA_USERNAME"
|
||||
echo "Password: $MOCHA_PASSWORD"
|
||||
echo ""
|
||||
echo "Your domain and IP address information is:"
|
||||
echo ""
|
||||
echo " $(hostname).privatesuv.com"
|
||||
ip addr show dev enp0s8 | grep inet
|
||||
echo ""
|
||||
echo "******************************************"
|
||||
echo ""
|
||||
|
||||
if [ $FIRSTRUN -eq 1 ]; then
|
||||
# register the SUV for automatic shutdown in 10 hours
|
||||
/usr/lib/mocha/spot_register_for_shutdown 600
|
||||
fi
|
||||
3
mocha-suv/common/libexec/spot_register_for_shutdown
Normal file
3
mocha-suv/common/libexec/spot_register_for_shutdown
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
echo "!!! This Spot Instance will automatically terminate in $1 minutes !!!"
|
||||
shutdown -P +$1
|
||||
@ -47,16 +47,17 @@ fi
|
||||
|
||||
cd machines/$SUV_NAME
|
||||
|
||||
cp templates/$SUV_TEMPLATE/$SUV_TEMPLATE.Vagrantfile ./Vagrantfile
|
||||
cp templates/$SUV_TEMPLATE/site.conf ./site.conf
|
||||
cp common/certs/localhost.key .
|
||||
cp common/certs/localhost.crt .
|
||||
# ln -s templates/$SUV_TEMPLATE/mocha-libexec ./mocha-libexec
|
||||
# cp templates/default/default.box ./default.box
|
||||
ln -s ../mocha-mysql/mocha-mysql/src/mocha-mysql ./sql
|
||||
ln -s ../mocha-php/mocha-php/src/mocha-php ./site
|
||||
ln -s ../mocha-common/mocha-common/data/libraries ./libraries
|
||||
ln -s ../mocha-common/mocha-common/data/uploads ./uploads
|
||||
#! REMEMBER: we are in machines/$SUV_NAME now !
|
||||
cp ../../templates/$SUV_TEMPLATE/$SUV_TEMPLATE.Vagrantfile ./Vagrantfile
|
||||
cp ../../templates/$SUV_TEMPLATE/site.conf ./site.conf
|
||||
cp ../../common/certs/localhost.key .
|
||||
cp ../../common/certs/localhost.crt .
|
||||
ln -s ../../common/libexec ./mocha-libexec
|
||||
# cp ../../templates/default/default.box ./default.box
|
||||
ln -s ../../../mocha-mysql/mocha-mysql/src/mocha-mysql ./sql
|
||||
ln -s ../../../mocha-php/mocha-php/src/mocha-php ./site
|
||||
ln -s ../../../mocha-common/mocha-common/data/libraries ./libraries
|
||||
ln -s ../../../mocha-common/mocha-common/data/uploads ./uploads
|
||||
|
||||
echo "enter sudo password to add entry to /etc/hosts if desired"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user