server/migractions.py
branchstable
changeset 3315 59220b704562
parent 3213 36a2357ccbc4
child 3230 1d25e928c299
child 3548 4cf5a360952e
equal deleted inserted replaced
3298:caef98aa4a98 3315:59220b704562
   114 
   114 
   115     def backup_database(self, backupfile=None, askconfirm=True):
   115     def backup_database(self, backupfile=None, askconfirm=True):
   116         config = self.config
   116         config = self.config
   117         repo = self.repo_connect()
   117         repo = self.repo_connect()
   118         # paths
   118         # paths
   119         timestamp = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
   119         timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
   120         instbkdir = osp.join(config.appdatahome, 'backup')
   120         instbkdir = osp.join(config.appdatahome, 'backup')
   121         if not osp.exists(instbkdir):
   121         if not osp.exists(instbkdir):
   122             os.makedirs(instbkdir)
   122             os.makedirs(instbkdir)
   123         backupfile = backupfile or osp.join(instbkdir, '%s-%s.tar.gz'
   123         backupfile = backupfile or osp.join(instbkdir, '%s-%s.tar.gz'
   124                                             % (config.appid, timestamp))
   124                                             % (config.appid, timestamp))
   413             return
   413             return
   414         repospschema = repoeschema.specializes()
   414         repospschema = repoeschema.specializes()
   415         espschema = eschema.specializes()
   415         espschema = eschema.specializes()
   416         if repospschema and not espschema:
   416         if repospschema and not espschema:
   417             self.rqlexec('DELETE X specializes Y WHERE X is CWEType, X name %(x)s',
   417             self.rqlexec('DELETE X specializes Y WHERE X is CWEType, X name %(x)s',
   418                          {'x': str(repoeschema)})
   418                          {'x': str(repoeschema)}, ask_confirm=False)
   419         elif not repospschema and espschema:
   419         elif not repospschema and espschema:
   420             self.rqlexec('SET X specializes Y WHERE X is CWEType, X name %(x)s, '
   420             self.rqlexec('SET X specializes Y WHERE X is CWEType, X name %(x)s, '
   421                          'Y is CWEType, Y name %(y)s',
   421                          'Y is CWEType, Y name %(y)s',
   422                          {'x': str(repoeschema), 'y': str(espschema)})
   422                          {'x': str(repoeschema), 'y': str(espschema)},
       
   423                          ask_confirm=False)
   423         self.rqlexecall(ss.updateeschema2rql(eschema),
   424         self.rqlexecall(ss.updateeschema2rql(eschema),
   424                         ask_confirm=self.verbosity >= 2)
   425                         ask_confirm=self.verbosity >= 2)
   425         for rschema, targettypes, role in eschema.relation_definitions(True):
   426         for rschema, targettypes, role in eschema.relation_definitions(True):
   426             if role == 'subject':
   427             if role == 'subject':
   427                 if not rschema in repoeschema.subject_relations():
   428                 if not rschema in repoeschema.subject_relations():
   957     def cmd_synchronize_permissions(self, ertype, commit=True):
   958     def cmd_synchronize_permissions(self, ertype, commit=True):
   958         self.cmd_sync_schema_props_perms(ertype, syncprops=False, commit=commit)
   959         self.cmd_sync_schema_props_perms(ertype, syncprops=False, commit=commit)
   959 
   960 
   960     # Workflows handling ######################################################
   961     # Workflows handling ######################################################
   961 
   962 
       
   963     def cmd_add_workflow(self, name, wfof, default=True, commit=False,
       
   964                          **kwargs):
       
   965         self.session.set_pool() # ensure pool is set
       
   966         wf = self.cmd_create_entity('Workflow', name=unicode(name),
       
   967                                     **kwargs)
       
   968         if not isinstance(wfof, (list, tuple)):
       
   969             wfof = (wfof,)
       
   970         for etype in wfof:
       
   971             rset = self.rqlexec(
       
   972                 'SET X workflow_of ET WHERE X eid %(x)s, ET name %(et)s',
       
   973                 {'x': wf.eid, 'et': etype}, 'x', ask_confirm=False)
       
   974             assert rset, 'unexistant entity type %s' % etype
       
   975             if default:
       
   976                 self.rqlexec(
       
   977                     'SET ET default_workflow X WHERE X eid %(x)s, ET name %(et)s',
       
   978                     {'x': wf.eid, 'et': etype}, 'x', ask_confirm=False)
       
   979         if commit:
       
   980             self.commit()
       
   981         return wf
       
   982 
       
   983     # XXX remove once cmd_add_[state|transition] are removed
       
   984     def _get_or_create_wf(self, etypes):
       
   985         self.session.set_pool() # ensure pool is set
       
   986         if not isinstance(etypes, (list, tuple)):
       
   987             etypes = (etypes,)
       
   988         rset = self.rqlexec('Workflow X WHERE X workflow_of ET, ET name %(et)s',
       
   989                             {'et': etypes[0]})
       
   990         if rset:
       
   991             return rset.get_entity(0, 0)
       
   992         return self.cmd_add_workflow('%s workflow' % ';'.join(etypes), etypes)
       
   993 
       
   994     @deprecated('use add_workflow and Workflow.add_state method')
   962     def cmd_add_state(self, name, stateof, initial=False, commit=False, **kwargs):
   995     def cmd_add_state(self, name, stateof, initial=False, commit=False, **kwargs):
   963         """method to ease workflow definition: add a state for one or more
   996         """method to ease workflow definition: add a state for one or more
   964         entity type(s)
   997         entity type(s)
   965         """
   998         """
   966         stateeid = self.cmd_add_entity('State', name=name, **kwargs)
   999         wf = self._get_or_create_wf(stateof)
   967         if not isinstance(stateof, (list, tuple)):
  1000         state = wf.add_state(name, initial, **kwargs)
   968             stateof = (stateof,)
  1001         if commit:
   969         for etype in stateof:
  1002             self.commit()
   970             # XXX ensure etype validity
  1003         return state.eid
   971             self.rqlexec('SET X state_of Y WHERE X eid %(x)s, Y name %(et)s',
  1004 
   972                          {'x': stateeid, 'et': etype}, 'x', ask_confirm=False)
  1005     @deprecated('use add_workflow and Workflow.add_transition method')
   973             if initial:
       
   974                 self.rqlexec('SET ET initial_state S WHERE ET name %(et)s, S eid %(x)s',
       
   975                              {'x': stateeid, 'et': etype}, 'x', ask_confirm=False)
       
   976         if commit:
       
   977             self.commit()
       
   978         return stateeid
       
   979 
       
   980     def cmd_add_transition(self, name, transitionof, fromstates, tostate,
  1006     def cmd_add_transition(self, name, transitionof, fromstates, tostate,
   981                            requiredgroups=(), conditions=(), commit=False, **kwargs):
  1007                            requiredgroups=(), conditions=(), commit=False, **kwargs):
   982         """method to ease workflow definition: add a transition for one or more
  1008         """method to ease workflow definition: add a transition for one or more
   983         entity type(s), from one or more state and to a single state
  1009         entity type(s), from one or more state and to a single state
   984         """
  1010         """
   985         treid = self.cmd_add_entity('Transition', name=name, **kwargs)
  1011         wf = self._get_or_create_wf(transitionof)
   986         if not isinstance(transitionof, (list, tuple)):
  1012         tr = wf.add_transition(name, fromstates, tostate, requiredgroups,
   987             transitionof = (transitionof,)
  1013                                conditions, **kwargs)
   988         for etype in transitionof:
  1014         if commit:
   989             # XXX ensure etype validity
  1015             self.commit()
   990             self.rqlexec('SET X transition_of Y WHERE X eid %(x)s, Y name %(et)s',
  1016         return tr.eid
   991                          {'x': treid, 'et': etype}, 'x', ask_confirm=False)
  1017 
   992         for stateeid in fromstates:
  1018     @deprecated('use Transition.set_transition_permissions method')
   993             self.rqlexec('SET X allowed_transition Y WHERE X eid %(x)s, Y eid %(y)s',
       
   994                          {'x': stateeid, 'y': treid}, 'x', ask_confirm=False)
       
   995         self.rqlexec('SET X destination_state Y WHERE X eid %(x)s, Y eid %(y)s',
       
   996                      {'x': treid, 'y': tostate}, 'x', ask_confirm=False)
       
   997         self.cmd_set_transition_permissions(treid, requiredgroups, conditions,
       
   998                                             reset=False)
       
   999         if commit:
       
  1000             self.commit()
       
  1001         return treid
       
  1002 
       
  1003     def cmd_set_transition_permissions(self, treid,
  1019     def cmd_set_transition_permissions(self, treid,
  1004                                        requiredgroups=(), conditions=(),
  1020                                        requiredgroups=(), conditions=(),
  1005                                        reset=True, commit=False):
  1021                                        reset=True, commit=False):
  1006         """set or add (if `reset` is False) groups and conditions for a
  1022         """set or add (if `reset` is False) groups and conditions for a
  1007         transition
  1023         transition
  1008         """
  1024         """
  1009         if reset:
  1025         self.session.set_pool() # ensure pool is set
  1010             self.rqlexec('DELETE T require_group G WHERE T eid %(x)s',
  1026         tr = self.session.entity_from_eid(treid)
  1011                          {'x': treid}, 'x', ask_confirm=False)
  1027         tr.set_transition_permissions(requiredgroups, conditions, reset)
  1012             self.rqlexec('DELETE T condition R WHERE T eid %(x)s',
  1028         if commit:
  1013                          {'x': treid}, 'x', ask_confirm=False)
  1029             self.commit()
  1014         for gname in requiredgroups:
  1030 
  1015             ### XXX ensure gname validity
  1031     @deprecated('use entity.fire_transition("transition") or entity.change_state("state")')
  1016             self.rqlexec('SET T require_group G WHERE T eid %(x)s, G name %(gn)s',
       
  1017                          {'x': treid, 'gn': gname}, 'x', ask_confirm=False)
       
  1018         if isinstance(conditions, basestring):
       
  1019             conditions = (conditions,)
       
  1020         for expr in conditions:
       
  1021             if isinstance(expr, str):
       
  1022                 expr = unicode(expr)
       
  1023             self.rqlexec('INSERT RQLExpression X: X exprtype "ERQLExpression", '
       
  1024                          'X expression %(expr)s, T condition X '
       
  1025                          'WHERE T eid %(x)s',
       
  1026                          {'x': treid, 'expr': expr}, 'x', ask_confirm=False)
       
  1027         if commit:
       
  1028             self.commit()
       
  1029 
       
  1030     def cmd_set_state(self, eid, statename, commit=False):
  1032     def cmd_set_state(self, eid, statename, commit=False):
  1031         self.session.set_pool() # ensure pool is set
  1033         self.session.set_pool() # ensure pool is set
  1032         entity = self.session.entity_from_eid(eid)
  1034         self.session.entity_from_eid(eid).change_state(statename)
  1033         entity.change_state(entity.wf_state(statename).eid)
       
  1034         if commit:
  1035         if commit:
  1035             self.commit()
  1036             self.commit()
  1036 
  1037 
  1037     # CWProperty handling ######################################################
  1038     # CWProperty handling ######################################################
  1038 
  1039 
  1045         value = unicode(value)
  1046         value = unicode(value)
  1046         try:
  1047         try:
  1047             prop = self.rqlexec('CWProperty X WHERE X pkey %(k)s', {'k': pkey},
  1048             prop = self.rqlexec('CWProperty X WHERE X pkey %(k)s', {'k': pkey},
  1048                                 ask_confirm=False).get_entity(0, 0)
  1049                                 ask_confirm=False).get_entity(0, 0)
  1049         except:
  1050         except:
  1050             self.cmd_add_entity('CWProperty', pkey=unicode(pkey), value=value)
  1051             self.cmd_create_entity('CWProperty', pkey=unicode(pkey), value=value)
  1051         else:
  1052         else:
  1052             self.rqlexec('SET X value %(v)s WHERE X pkey %(k)s',
  1053             self.rqlexec('SET X value %(v)s WHERE X pkey %(k)s',
  1053                          {'k': pkey, 'v': value}, ask_confirm=False)
  1054                          {'k': pkey, 'v': value}, ask_confirm=False)
  1054 
  1055 
  1055     # other data migration commands ###########################################
  1056     # other data migration commands ###########################################
  1056 
  1057 
       
  1058     def cmd_create_entity(self, etype, *args, **kwargs):
       
  1059         """add a new entity of the given type"""
       
  1060         commit = kwargs.pop('commit', False)
       
  1061         self.session.set_pool()
       
  1062         entity = self.session.create_entity(etype, *args, **kwargs)
       
  1063         if commit:
       
  1064             self.commit()
       
  1065         return entity
       
  1066 
       
  1067     @deprecated('use create_entity')
  1057     def cmd_add_entity(self, etype, *args, **kwargs):
  1068     def cmd_add_entity(self, etype, *args, **kwargs):
  1058         """add a new entity of the given type"""
  1069         """add a new entity of the given type"""
  1059         rql = 'INSERT %s X' % etype
  1070         return self.cmd_create_entity(etype, *args, **kwargs).eid
  1060         relations = []
       
  1061         restrictions = []
       
  1062         for rtype, rvar in args:
       
  1063             relations.append('X %s %s' % (rtype, rvar))
       
  1064             restrictions.append('%s eid %s' % (rvar, kwargs.pop(rvar)))
       
  1065         commit = kwargs.pop('commit', False)
       
  1066         for attr in kwargs:
       
  1067             relations.append('X %s %%(%s)s' % (attr, attr))
       
  1068         if relations:
       
  1069             rql = '%s: %s' % (rql, ', '.join(relations))
       
  1070         if restrictions:
       
  1071             rql = '%s WHERE %s' % (rql, ', '.join(restrictions))
       
  1072         eid = self.rqlexec(rql, kwargs, ask_confirm=self.verbosity>=2).rows[0][0]
       
  1073         if commit:
       
  1074             self.commit()
       
  1075         return eid
       
  1076 
  1071 
  1077     def sqlexec(self, sql, args=None, ask_confirm=True):
  1072     def sqlexec(self, sql, args=None, ask_confirm=True):
  1078         """execute the given sql if confirmed
  1073         """execute the given sql if confirmed
  1079 
  1074 
  1080         should only be used for low level stuff undoable with existing higher
  1075         should only be used for low level stuff undoable with existing higher