class Invitation(models.Model): person = models.ForeignKey(Person, related_name='invitations') invited_by = models.ForeignKey(Person, related_name='sent_invitations') email = models.EmailField() message = models.TextField(null=True, blank=True) datetime = models.DateTimeField(auto_now_add=True) uuid = uuidfield.UUIDField(auto=True) def is_expired(self): return hasattr(self.person, 'user') def send(self): subject = _("Invitation to V LO graduates community.") context = { 'person': self.person, 'invited_by': self.invited_by, 'message': self.message } send_templated_email( subject, 'community/invite.html', context, [self.email], )
class Migration(migrations.Migration): dependencies = [] operations = [ migrations.CreateModel( name='DbOwnersManagerTable', fields=[ ('customer_id', uuidfield.UUIDField(primary_key=True, serialize=False, editable=False, max_length=32, blank=True, unique=True)), ('customer_name', models.CharField(unique=True, max_length=100)), ('customer_description', models.CharField(max_length=500)), ('db_manager_settings', models.CharField(max_length=2000)), ('creation_time', models.DateTimeField(auto_now_add=True, null=True)), ('last_update_time', models.DateTimeField(auto_now=True, null=True)), ('wx_appid', models.CharField(max_length=200)), ('wx_appsecret', models.CharField(max_length=200)), ], options={}, bases=(models.Model, ), ), migrations.CreateModel( name='WeixinUser', fields=[ ('weixinuser_id', models.CharField(max_length=50, serialize=False, primary_key=True)), ('nick_name', models.CharField(max_length=150)), ('creation_time', models.DateTimeField(auto_now_add=True, null=True)), ('last_message_time', models.DateTimeField(auto_now=True, null=True)), ('menu_flag', models.SmallIntegerField(default=0)), ('person_loate', models.CharField(max_length=100)), ('person_deliver_info', models.BinaryField(max_length=1000)), ('user_is_subscribe', models.IntegerField(default=0)), ('user_wx_nickname', models.BinaryField(max_length=200)), ('user_wx_sex', models.IntegerField(default=0)), ('user_wx_img', models.CharField(max_length=500)), ('user_wx_subscribe_time', models.IntegerField(default=0)), ('user_wx_remark', models.CharField(max_length=500)), ('user_wx_group_id', models.IntegerField(default=0)), ('user_last_wx_info_update_time', models.DateTimeField(null=True)), ], options={}, bases=(models.Model, ), ), ]
class Invitation(models.Model): person = models.ForeignKey(Person, related_name='invitations') invited_by = models.ForeignKey(Person, related_name='sent_invitations') email = models.EmailField() message = models.TextField(null=True, blank=True) datetime = models.DateTimeField(auto_now_add=True) uuid = uuidfield.UUIDField(auto=True) def is_expired(self): return hasattr(self.person, 'user')
class Job(models.Model): STATES = Choices("NEW", "READY", "PROCESSING", "FAILED", "COMPLETE") id = uuidfield.UUIDField(primary_key=True, auto=True, db_index=True) created = models.DateTimeField(auto_now_add=True, db_index=True) modified = models.DateTimeField(auto_now=True) name = models.CharField(max_length=100) state = models.CharField(max_length=20, choices=STATES, default=STATES.NEW, db_index=True) next_task = models.CharField(max_length=100, blank=True) workspace = JSONField(null=True) queue_name = models.CharField(max_length=20, default='default', db_index=True) class Meta: ordering = ['-created'] objects = JobManager() def save(self, *args, **kwargs): if not self.pk: self.next_task = get_next_task_name(self.name) self.workspace = self.workspace or {} try: self.run_creation_hook() except Exception as exception: # noqa logger.exception( "Failed to create new job, creation hook raised an exception" ) return # cancel the save return super(Job, self).save(*args, **kwargs) def update_next_task(self): self.next_task = get_next_task_name(self.name, self.next_task) or '' def get_failure_hook_name(self): return get_failure_hook_name(self.name) def get_creation_hook_name(self): return get_creation_hook_name(self.name) def run_creation_hook(self): creation_hook_name = self.get_creation_hook_name() if creation_hook_name: logger.info("Running creation hook %s for new job", creation_hook_name) creation_hook_function = import_by_path(creation_hook_name) creation_hook_function(self)
class LoadBalancer(models.Model): """ Load balancers adhere to a `protocol` (http and tcp for now). For rackspace, the endpoint is set until the load balancer is deleted. For docker, the endpoint will change on each system startup. port_name is the name of the instance port that should be used to propagate to the lb backend. """ id = uuidfield.UUIDField(primary_key=True) port_name = models.TextField(validators=[alphanumeric]) protocol = models.CharField(max_length=10, choices=(('http', 'http'), ('tcp', 'tcp'))) options = jsonfield.JSONField(default={}) @classmethod def create(cls, group, port_name, protocol, options={}): """ :Parameters: - `options`: { 'securePort': 443, 'sslTermination': True, 'secureTrafficOnly': False, 'certificate': '<cert>', 'privatekey': '<key>' } """ lb_id = uuid.uuid4().hex lb = cls(id=lb_id, port_name=port_name, protocol=protocol, options=options) lb.group = group host, port = lb.backend.create_lb(lb) # Add key to config lb.group.environment.system.config_manager.set( lb.config_key, json.dumps({ 'host': host, 'port': port })) # Add group to endpoint supervisor endpoints = supervisors.endpoint_supervisor_client() endpoints.add_group(lb.group.pk, lb.group.config_key) lb.save() return lb def add_endpoint(self, endpoint): """ Chooses and adds an endpoint to the load balancer. :Parameters: - `endpoint`: { 'host': '11.22.33.44', 'ports': {'http': 80, 'https': 443} } """ self._apply_endpoint(self.backend.lb_add_endpoint, endpoint) def remove_endpoint(self, endpoint): """ Chooses and removes an endpoint from the load balancer. :Parameters: - `endpoint`: { 'host': '11.22.33.44', 'ports': {'http': 80, 'https': 443} } """ self._apply_endpoint(self.backend.lb_remove_endpoint, endpoint) def _apply_endpoint(self, func, endpoint): host = endpoint['host'] port = endpoint['ports'].get(self.port_name) if port != None: func(self, host, port) else: log.info('Unable to find port with name "%s"' % self.port_name) @property def backend(self): backend = self.group.environment.backend if not backend: raise Exception('no backend defined for environment') return backend @property def config_key(self): """ Returns the load balancer's key in the configuration manager. """ return self.group.environment.system.config_manager.get_lb_key(self) @classmethod def pre_delete(cls, sender, instance, **kwargs): lb = instance # Remove group from endpoint supervisor endpoints = supervisors.endpoint_supervisor_client() endpoints.remove_group(lb.group.pk) # Remove key from config lb.group.environment.system.config_manager.delete(lb.config_key) lb.backend.delete_lb(lb)
class Instance(AuditedModel): """ A running instance of a node. """ id = uuidfield.UUIDField(auto=True, primary_key=True) environment = models.ForeignKey('Environment', related_name='instances') host = models.ForeignKey('Host', related_name='instances') node = models.ForeignKey('Node', related_name='instances') @classmethod def create(cls, env, host, node): """ Creates an instance through the host's agent. :Parameters: - `env`: the instance's environment. - `host`: the instance's host. - `node`: the instance's node. """ instance = cls(environment=env, host=host, node=node) instance.save() # REM: block instance.sync_node(node) # REM: block host.agent.add_instance(instance) return instance def sync_node(self, node): """ Sync the instance's node to the agent. The node will be pulled if it isn't there already. :Parameters: - `node`: the node to sync """ # REM: block if node not in self.host.nodes: self.host.agent.add_node(node) if self.environment.current_release: # Use the environment's release self.host.agent.pull(node, release=self.environment.current_release) elif self.environment.using_source: self.host.agent.pull(node) else: # Environment has not yet been deployed to pass def reload(self): """ Since reload is only used in development, there is no need to update the load balancer. """ return self.host.agent.reload_instance(self) @property def load_balancer(self): """ Returns the instance's parent load balancer. """ if self.host.group: return self.host.group.load_balancer return None @property def config_key(self): """ Returns the instance's key in the configuration manager. """ return self.environment.system.config_manager.get_instance_key(self) def restart(self): """ When the agent restarts an instance, it restarts with the newest revision of the node. Restarting should take place after the host pulls its nodes. """ # Restart instance self.safe_run(self.host.agent.restart_instance) def safe_run(self, func): """ If the instance belongs to a load balancer, `func` is run while mirroring instance state to the load balancer. Restarting or removing any instance belonging to a load balancer uses a block/unblock pattern. This ensures that the endpoint manager does not remove the endpoint on its own. Since we must know the exact time the endpoint is removed from the load balancer, `_safe_run` removes it manually. :Parameters: - `func`: the function to safely run. """ if self.load_balancer: # Have endpoint manager block (ignore) this instance endpoints = supervisors.endpoint_supervisor_client() endpoints.block_instance(self.pk) # Manually remove the instance's endpoint from the load balancer config_manager = self.environment.system.config_manager endpoint = json.loads(config_manager.get(self.config_key)) self.load_balancer.remove_endpoint(endpoint) # Run `func` now that instance state is mirrored to its load balancer func(self) if self.load_balancer: # Have endpoint manager unblock this instance endpoints.unblock_instance(self.pk) @classmethod def pre_delete(cls, sender, instance, **kwargs): """ Deletes the instance through the host's agent. """ # Remove instance instance.safe_run(instance.host.agent.remove_instance)
class RegistrationProfile(models.Model): """ A simple profile which stores an activation key for use during user account registration. Generally, you will not want to interact directly with instances of this model; the provided manager includes methods for creating and activating new accounts, as well as for cleaning out accounts which have never been activated. While it is possible to use this model as the value of the ``AUTH_PROFILE_MODULE`` setting, it's not recommended that you do so. This model's sole purpose is to store data temporarily during account registration and activation. """ user = models.ForeignKey(User, unique=True, verbose_name=_('user')) activation_key = uuidfield.UUIDField(auto=True) is_activated = models.BooleanField(default=False) objects = RegistrationManager() class Meta: verbose_name = _('registration profile') verbose_name_plural = _('registration profiles') def __unicode__(self): return u"Registration information for %s" % self.user def activation_key_expired(self): """ Determine whether this ``RegistrationProfile``'s activation key has expired, returning a boolean -- ``True`` if the key has expired. Key expiration is determined by a two-step process: 1. If the user has already activated, the key will have been reset to the string constant ``ACTIVATED``. Re-activating is not permitted, and so this method returns ``True`` in this case. 2. Otherwise, the date the user signed up is incremented by the number of days specified in the setting ``ACCOUNT_ACTIVATION_DAYS`` (which should be the number of days after signup during which a user is allowed to activate their account); if the result is less than or equal to the current date, the key has expired and this method returns ``True``. """ expiration_date = datetime.timedelta( days=settings.ACCOUNT_ACTIVATION_DAYS) return self.is_activated or (self.user.date_joined + expiration_date <= datetime_now()) activation_key_expired.boolean = True def send_activation_email(self): """ Send an activation email to the user associated with this ``RegistrationProfile``. The activation email will make use of two templates: ``registration/activation_email_subject.txt`` This template will be used for the subject line of the email. Because it is used as the subject line of an email, this template's output **must** be only a single line of text; output longer than one line will be forcibly joined into only a single line. ``registration/activation_email.txt`` This template will be used for the body of the email. These templates will each receive the following context variables: ``activation_key`` The activation key for the new account. ``expiration_days`` The number of days remaining during which the account may be activated. """ ctx_dict = { 'activation_key': self.activation_key, 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS, } subject = render_to_string('registration/activation_email_subject.txt', ctx_dict) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) message = { 'template': 'registration/activation_email.html', 'context': ctx_dict } self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
class Migration(migrations.Migration): dependencies = [] operations = [ migrations.CreateModel( name='Device', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('device_name', models.CharField(max_length=100)), ('device_description', models.CharField(default=None, max_length=100)), ('register_time', models.DateTimeField(auto_now_add=True, null=True)), ], options={}, bases=(models.Model, ), ), migrations.CreateModel( name='Group', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('group_name', models.CharField(max_length=20)), ('group_description', models.CharField(max_length=150)), ], options={}, bases=(models.Model, ), ), migrations.CreateModel( name='JobSeqs', fields=[ ('jobID', uuidfield.UUIDField(primary_key=True, serialize=False, editable=False, max_length=32, blank=True, unique=True)), ('job_creationTime', models.DateTimeField(auto_now_add=True)), ('job_content', models.CharField(max_length=200)), ('job_status', models.SmallIntegerField()), ('job_description', models.CharField(default=None, max_length=200)), ], options={}, bases=(models.Model, ), ), migrations.CreateModel( name='WeixinUser', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('weixinUserID', models.CharField(max_length=30)), ('creation_time', models.DateTimeField(auto_now_add=True, null=True)), ('lastmessagetime', models.DateTimeField(auto_now_add=True, null=True)), ('lastconnectiontime', models.DateTimeField(auto_now=True, null=True)), ('menu_flag', models.SmallIntegerField(default=0)), ('belong_group', models.ForeignKey(to='wxapi.Group', null=True)), ], options={}, bases=(models.Model, ), ), migrations.AddField( model_name='jobseqs', name='operator_user', field=models.ForeignKey(to='wxapi.WeixinUser', null=True), preserve_default=True, ), migrations.AddField( model_name='jobseqs', name='target_device', field=models.OneToOneField(null=True, to='wxapi.Device'), preserve_default=True, ), migrations.AddField( model_name='device', name='belong_group', field=models.ForeignKey(to='wxapi.Group', null=True), preserve_default=True, ), ]
class Survey(models.Model): uuid = uuidfield.UUIDField(auto=True, version=4, hyphenate=True) created_at = models.DateTimeField(default=timezone.now) updated_at = models.DateTimeField(auto_now=True) # This field stores the running total of all of the collected salaries # while salaries are being collected, and the average salary if collection # has completed. total = models.BigIntegerField(default=get_default_total) # The tracker field stores a VERY large number that is used to enforce one # response per participant. Each link sent to a participant has a large # prime number embedded in it. Each time a response is entered, the # `tracker` number is multiplied by that number. This way, we can know if # someone has already responded by checking to see if the tracker number is # divisible by the prime that was assigned to them. _tracker = models.CharField(default='1', max_length=10000, null=True) num_collected = models.PositiveIntegerField(default=0, null=True) num_expected = models.PositiveIntegerField(null=True) @property def tracker(self): if self._tracker is None: return None return long(self._tracker) @tracker.setter def tracker(self, value): if value is None: self._tracker = None else: self._tracker = str(value) def has_key_been_recorded(self, key): if self.tracker is None: return None return self.tracker % key == 0 def record_salary(self, salary, key): if self.has_key_been_recorded(key): raise ValueError("This key has already recorded a salary") self.tracker *= key self.total += salary self.num_collected += 1 self.save() @property def is_open(self): return self.tracker is not None @property def is_finalized(self): return not self.is_open @property def is_finalizable(self): return self.num_collected >= 4 def finalize(self, seed): if not self.is_finalizable: raise ValueError( "Survey must have at least 4 responses to be finalized") total = self.total - seed self.total = total / self.num_collected self.num_collected = None self.num_expected = None self.tracker = None self.save()