def get(self, request, *args, **kwargs): hostname = self.getParam(request, 'hostname', '') product = LogicProducts().get_product(request, False) action = self.getParam(request, 'action', '') if action == "install": instance_status = [ SaasInstance().IN_PREPARATION, ] elif action == "update" or action == "check" or action == "quota": instance_status = [ SaasInstance().READY, SaasInstance().AVAILABLE, SaasInstance().RESERVED, SaasInstance().ASSIGNED, SaasInstance().EXPIRED, SaasInstance().TO_BE_REMOVED, ] elif action == "remove": instance_status = [ SaasInstance().TO_BE_REMOVED, ] else: raise Exception('please specify valid action') if hostname and product: rows = SaasInstance.objects.filter( hostname=hostname, product=product, status__in=instance_status).order_by('id') else: raise Exception('please specify hostname and product_name') serializer = InstanceSerializer(rows, many=True) return Response(serializer.data, status=status.HTTP_200_OK)
def create_new_instance(self, hostname, pacuser, product): # generate new password new_password = self.random_password(False) # generate the db password db_password = self.random_password(False) # the activation token that allows us to activate the instance activation_token = self.random_password(False) # find new available identifier instance_id_start = settings.INSTANCE_ID_START instance_id_end = settings.INSTANCE_ID_END startport = settings.PORT_START endport = settings.PORT_END new_id = random.randrange(instance_id_start, instance_id_end) while SaasInstance.objects.filter(identifier=str(new_id)).exists(): new_id = random.randrange(instance_id_start, instance_id_end) # find new available port on that host, independant of the product new_port = -1 last_port = -1 if product.number_of_ports > 0: if SaasInstance.objects.filter(hostname=hostname).exists(): with connection.cursor() as cursor: sql = """SELECT MAX(last_port) FROM saas_instance WHERE hostname = %s""" cursor.execute(sql, [ hostname, ]) port_result = cursor.fetchone() if port_result: new_port = port_result[0] + 1 if new_port < startport: new_port = startport last_port = new_port + product.number_of_ports - 1 if new_port > endport: return False, {} # store to database instance = SaasInstance.objects.create( identifier=str(new_id), hostname=hostname, pacuser=pacuser, activation_token=activation_token, product=product, first_port=new_port, last_port=last_port, initial_password=new_password, password1=self.random_password(False), password2=self.random_password(False), db_password=db_password, status=SaasInstance().IN_PREPARATION) # return the result return True, { 'new_id': new_id, 'new_password': new_password, 'db_password': db_password, 'hostname': hostname, 'port': new_port }
def assign_instance(self, customer, product, plan): # check for first available instance instance = SaasInstance.objects.filter(product=product).filter( status=SaasInstance().AVAILABLE).first() if not instance: # send message to administrator self.notify_administrators( _("Missing free instance for %s") % (product.name, ), _("Assigning of %s instance for customer %d failed") % (product.name, customer.id)) # TODO if no instance is available, then add the user to the waiting list return False else: # assign a free instance # there might be an unconfirmed contract already contract = LogicContracts().get_contract(customer, product) if not contract: contract = LogicContracts().get_new_contract( customer, product, plan) contract.instance = instance contract.plan = plan contract.is_confirmed = True contract.save() instance.status = instance.ASSIGNED instance.save() # call activation url of hosted application [success, PasswordResetToken ] = LogicInstances().activate_instance(customer, product, instance) if not success: # send message to administrator self.notify_administrators( _("SaasAdmin Error during activation"), _("Failed activation of %s instance %s for customer %d") % (product.name, instance.identifier, customer.id)) return False # send message to administrator instances_available = LogicInstances( ).get_number_of_available_instances(product) self.notify_administrators( _("Instance for %s assigned") % (product.name, ), _("Nice, an instance of %s was booked for customer %d") % (product.name, customer.id) + "\n" + _("Still %d instances are available for new customers.") % (instances_available, )) # TODO send invoice to customer, or send it later in batch processing? return True
def instances(request, product): product = SaasProduct.objects.filter(slug = product).first() unused_instances = SaasInstance.objects.filter(product = product).filter(Q(status=SaasInstance().AVAILABLE) | Q(status=SaasInstance().READY) | Q(status=SaasInstance().IN_PREPARATION)) return render(request,"instances.html", {'unused_instances': unused_instances, 'product': product })
def get_number_of_available_instances(self, product): return SaasInstance.objects.filter(product=product).filter( status=SaasInstance().AVAILABLE).count()
def mark_deactivated_instances_for_deletion(self): """ to be called by a cronjob each night """ contracts = SaasContract.objects.filter(is_confirmed = True, \ is_auto_renew = False, end_date__lt = datetime.today(), instance__status = SaasInstance().EXPIRED) for contract in contracts: days = 30 if contract.plan.period_length_in_months == 0: if contract.plan.period_length_in_days == 1: # for the one day test instance, remove it immediately days = 0 elif contract.plan.period_length_in_days > 0: # for other test instances, remove it after 3 days days = 3 if contract.end_date + timedelta( days=days) < datetime.today().date(): instance = contract.instance instance.status = instance.TO_BE_REMOVED instance.save()
def deactivate_expired_instances(self): """ to be called by a cronjob each night """ contracts = SaasContract.objects.filter(is_confirmed = True, \ is_auto_renew = False, end_date__lt = datetime.today(), instance__status = SaasInstance().ASSIGNED) for contract in contracts: instance = contract.instance if self.deactivate_instance(instance.product, instance): instance.status = instance.EXPIRED instance.save()