def add_template(template, **kwargs): """ Add template and a type and typeattrs. """ tmpl = Template() tmpl.name = template.name tmpl.created_by = kwargs.get('user_id') if template.parent_id: tmpl.parent_id = template.parent_id if template.description: tmpl.description = template.description if template.layout: tmpl.layout = get_json_as_string(template.layout) if template.project_id: tmpl.project_id = template.project_id db.DBSession.add(tmpl) if template.templatetypes is not None: types = template.templatetypes for templatetype in types: ttype = _update_templatetype(templatetype, **kwargs) tmpl.templatetypes.append(ttype) db.DBSession.flush() log.info("[Added template]\n{}".format(template)) return tmpl
def add_child_template(parent_id, name, description=None, **kwargs): """ Add template and a type and typeattrs. """ parent_template = db.DBSession.query(Template).filter( Template.id == parent_id).one() tmpl = Template() tmpl.name = name if description is not None: tmpl.description = description else: tmpl.description = parent_template.description tmpl.layout = parent_template.layout tmpl.parent_id = parent_id #now add a default network type, but only if the parent has one defined parent_type = _get_network_type(parent_id) if parent_type is not None: network_type = TemplateType() network_type.name = "{}-network".format(tmpl.name) network_type.resource_type = 'NETWORK' network_type.parent_id = parent_type.id network_type.status = 'A' tmpl.templatetypes.append(network_type) else: log.warn( "Unable to set a network type on this template as its " "parent %s does not contain one, so cannot create a " "parent-child relationship.", parent_id) db.DBSession.add(tmpl) db.DBSession.flush() return tmpl
def import_template_dict(template_dict, allow_update=True, **kwargs): user_id = kwargs.get('user_id') template_file_j = template_dict file_attributes = template_file_j.get('attributes') file_datasets = template_file_j.get('datasets', {}) template_j = JSONObject(template_file_j.get('template', {})) #default datasets are optional, so don't force them to exist in the structure default_datasets_j = {} for k, v in file_datasets.items(): default_datasets_j[int(k)] = Dataset(v) if file_attributes is None or len(template_j) == 0: raise HydraError("Invalid template. The template must have the following structure: " + \ "{'attributes':\\{...\\}, 'datasets':\\{...\\}, 'template':\\{...\\}}") #Normalise attribute IDs so they're always ints (in case they're specified as strings) attributes_j = {} for k, v in file_attributes.items(): attributes_j[int(k)] = JSONObject(v) template_name = template_j.name template_description = template_j.description template_layout = None if template_j.layout is not None: if isinstance(template_j.layout, dict): template_layout = json.dumps(template_j.layout) else: template_layout = template_j.layout try: template_i = db.DBSession.query(Template).filter( Template.name == template_name).options( joinedload('templatetypes').joinedload('typeattrs').joinedload( 'attr')).one() if allow_update == False: raise HydraError("Existing Template Found with name %s" % (template_name, )) else: template_i.layout = template_layout template_i.description = template_description except NoResultFound: log.debug("Template not found. Creating new one. name=%s", template_name) template_i = Template(name=template_name, description=template_description, layout=template_layout) db.DBSession.add(template_i) types_j = template_j.templatetypes type_id_map = {r.id: r for r in template_i.templatetypes} #Delete any types which are in the DB but no longer in the JSON file type_name_map = {r.name: r.id for r in template_i.templatetypes} attr_name_map = {} for type_i in template_i.templatetypes: for typeattr in type_i.typeattrs: attr_name_map[typeattr.attr.name] = (typeattr.attr_id, typeattr.type_id) existing_types = set([r.name for r in template_i.templatetypes]) log.debug( ["%s : %s" % (tt.name, tt.id) for tt in template_i.templatetypes]) log.debug("Existing types: %s", existing_types) new_types = set([t.name for t in types_j]) log.debug("New Types: %s", new_types) types_to_delete = existing_types - new_types log.debug("Types to delete: %s", types_to_delete) log.debug(type_name_map) for type_to_delete in types_to_delete: type_id = type_name_map[type_to_delete] try: for i, tt in enumerate(template_i.templatetypes): if tt.id == type_id: type_i = template_i.templatetypes[i] #first remove all the type attributes associated to the type for ta_i in type_i.typeattrs: db.DBSession.delete(ta_i) del (template_i.templatetypes[i]) log.debug("Deleting type %s (%s)", type_i.name, type_i.id) del (type_name_map[type_to_delete]) db.DBSession.delete(type_i) except NoResultFound: pass #Add or update types. for type_j in types_j: type_name = type_j.name #check if the type is already in the DB. If not, create a new one. type_is_new = False if type_name in existing_types: type_id = type_name_map[type_name] type_i = type_id_map[type_id] else: log.debug("Type %s not found, creating new one.", type_name) type_i = TemplateType() type_i.name = type_name template_i.templatetypes.append(type_i) type_i.status = 'A' ## defaults to active type_is_new = True if type_j.description is not None: type_i.description = type_j.description if type_j.alias is not None: type_i.alias = type_j.alias #Allow 'type' or 'resource_type' to be accepted if type_j.type is not None: type_i.resource_type = type_j.type elif type_j.resource_type is not None: type_i.resource_type = type_j.resource_type if type_j.resource_type is None: raise HydraError("No resource type specified." " 'NODE', 'LINK', 'GROUP' or 'NETWORK'") if type_j.layout is not None: if isinstance(type_j, dict): type_i.layout = json.dumps(type_j.layout) else: type_i.layout = type_j.layout #delete any TypeAttrs which are in the DB but not in the JSON file existing_attrs = [] if not type_is_new: for r in template_i.templatetypes: if r.name == type_name: for typeattr in r.typeattrs: existing_attrs.append(typeattr.attr.name) existing_attrs = set(existing_attrs) type_attrs = [] for typeattr_j in type_j.typeattrs: if typeattr_j.attr_id is not None: attr_j = attributes_j[typeattr_j.attr_id].name elif typeattr_j.attr is not None: attr_j = typeattr_j.attr.name type_attrs.append(attr_j) type_attrs = set(type_attrs) attrs_to_delete = existing_attrs - type_attrs for attr_to_delete in attrs_to_delete: attr_id, type_id = attr_name_map[attr_to_delete] try: attr_i = db.DBSession.query(TypeAttr).filter( TypeAttr.attr_id == attr_id, TypeAttr.type_id == type_id).options( joinedload('attr')).one() db.DBSession.delete(attr_i) log.debug("Attr %s in type %s deleted", attr_i.attr.name, attr_i.templatetype.name) except NoResultFound: log.debug("Attr %s not found in type %s" % (attr_id, type_id)) continue #Add or update type typeattrs #Support an external attribute dict or embedded attributes. for typeattr_j in type_j.typeattrs: if typeattr_j.attr_id is not None: attr_j = attributes_j[typeattr_j.attr_id] elif typeattr_j.attr is not None: attr_j = typeattr_j.attr default_dataset_j = None if typeattr_j.default_dataset is not None: default_dataset_j = typeattr_j.default_dataset elif typeattr_j.default is not None: # for backward compatibility default_dataset_j = typeattr_j.default elif typeattr_j.default_dataset_id is not None: default_dataset_j = default_datasets_j[int( typeattr_j.default_dataset_id)] parse_json_typeattr(type_i, typeattr_j, attr_j, default_dataset_j, user_id=user_id) db.DBSession.flush() return template_i
def import_template_xml(template_xml, allow_update=True, **kwargs): """ Add the template, type and typeattrs described in an XML file. Delete type, typeattr entries in the DB that are not in the XML file The assumption is that they have been deleted and are no longer required. """ user_id = kwargs.get('user_id') template_xsd_path = config.get('templates', 'template_xsd_path') xmlschema_doc = etree.parse(template_xsd_path) xmlschema = etree.XMLSchema(xmlschema_doc) xml_tree = etree.fromstring(template_xml) xmlschema.assertValid(xml_tree) template_name = xml_tree.find('template_name').text template_description = xml_tree.find('template_description') if template_description is not None: template_description = template_description.text template_layout = None if xml_tree.find('layout') is not None and \ xml_tree.find('layout').text is not None: layout = xml_tree.find('layout') layout_string = get_etree_layout_as_dict(layout) template_layout = json.dumps(layout_string) try: tmpl_i = db.DBSession.query(Template).filter(Template.name == template_name)\ .options(joinedload('templatetypes') .joinedload('typeattrs') .joinedload('attr')).one() if allow_update == False: raise HydraError("Existing Template Found with name %s" % (template_name, )) else: log.debug("Existing template found. name=%s", template_name) tmpl_i.layout = template_layout tmpl_i.description = template_description except NoResultFound: log.debug("Template not found. Creating new one. name=%s", template_name) tmpl_i = Template(name=template_name, description=template_description, layout=template_layout) db.DBSession.add(tmpl_i) types = xml_tree.find('resources') #Delete any types which are in the DB but no longer in the XML file type_name_map = {r.name: r.id for r in tmpl_i.templatetypes} attr_name_map = {} for type_i in tmpl_i.templatetypes: for typeattr in type_i.typeattrs: attr_name_map[typeattr.attr.name] = (typeattr.attr.id, typeattr.type_id) existing_types = set([r.name for r in tmpl_i.templatetypes]) new_types = set([r.find('name').text for r in types.findall('resource')]) types_to_delete = existing_types - new_types for type_to_delete in types_to_delete: type_id = type_name_map[type_to_delete] try: type_i = db.DBSession.query(TemplateType).filter( TemplateType.id == type_id).one() log.debug("Deleting type %s", type_i.name) db.DBSession.delete(type_i) except NoResultFound: pass #Add or update types. for resource in types.findall('resource'): type_name = resource.find('name').text #check if the type is already in the DB. If not, create a new one. type_is_new = False if type_name in existing_types: type_id = type_name_map[type_name] type_i = db.DBSession.query(TemplateType).filter( TemplateType.id == type_id).options( joinedload('typeattrs').joinedload('attr')).one() else: log.debug("Type %s not found, creating new one.", type_name) type_i = TemplateType() type_i.name = type_name tmpl_i.templatetypes.append(type_i) type_is_new = True if resource.find('alias') is not None: type_i.alias = resource.find('alias').text if resource.find('description') is not None: type_i.description = resource.find('description').text if resource.find('type') is not None: type_i.resource_type = resource.find('type').text if resource.find('layout') is not None and \ resource.find('layout').text is not None: layout = resource.find('layout') layout_string = get_etree_layout_as_dict(layout) type_i.layout = json.dumps(layout_string) #delete any TypeAttrs which are in the DB but not in the XML file existing_attrs = [] if not type_is_new: for r in tmpl_i.templatetypes: if r.name == type_name: for typeattr in r.typeattrs: existing_attrs.append(typeattr.attr.name) existing_attrs = set(existing_attrs) template_attrs = set( [r.find('name').text for r in resource.findall('attribute')]) attrs_to_delete = existing_attrs - template_attrs for attr_to_delete in attrs_to_delete: attr_id, type_id = attr_name_map[attr_to_delete] try: attr_i = db.DBSession.query(TypeAttr).filter( TypeAttr.attr_id == attr_id, TypeAttr.type_id == type_id).options( joinedload('attr')).one() db.DBSession.delete(attr_i) log.debug("Attr %s in type %s deleted", attr_i.attr.name, attr_i.templatetype.name) except NoResultFound: log.debug("Attr %s not found in type %s", attr_id, type_id) continue #Add or update type typeattrs for attribute in resource.findall('attribute'): new_typeattr = _parse_xml_typeattr(type_i, attribute, user_id=user_id) db.DBSession.flush() return tmpl_i