def delete(self, *args, **kwargs): """ Overrides the delete method so that a database can be put in quarantine and not removed """ #do_something() if self.is_in_quarantine: LOG.warning("Database %s is in quarantine and will be removed" % self.name) for credential in self.credentials.all(): instance = factory_for(self.databaseinfra) instance.remove_user(credential) super(Database, self).delete(*args, **kwargs) # Call the "real" delete() method. else: LOG.warning("Putting database %s in quarantine" % self.name) if self.credentials.exists(): for credential in self.credentials.all(): new_password = make_db_random_password() new_credential = Credential.objects.get(pk=credential.id) new_credential.password = new_password new_credential.save() instance = factory_for(self.databaseinfra) instance.update_user(new_credential) else: LOG.info("There is no credential on this database: %s" % self.databaseinfra) self.is_in_quarantine = True self.quarantine_dt = datetime.datetime.now().date() self.save()
def service_status(request, engine_name=None, engine_version=None, service_name=None): """ To check the status of an databaseinfra, tsuru uses the url /resources/<service_name>/status. If the databaseinfra is ok, this URL should return 204. """ engine = __check_service_availability(engine_name, engine_version) if not engine: return Response(data={ "error": "endpoint not available for %s(%s)" % (engine_name, engine_version) }, status=500) data = request.DATA LOG.info("status for service %s" % (service_name)) try: databaseinfra = DatabaseInfra.objects.get(name=service_name) factory_for(databaseinfra).check_status() return Response(data={"status": "ok"}, status=204) except DatabaseInfra.DoesNotExist: LOG.warning("databaseinfra not found for service %s" % (service_name)) return Response(data={"status": "not_found"}, status=404) except Exception, e: return Response(data={"error": "%s" % e}, status=500)
def delete(self, *args, **kwargs): if self.is_in_quarantine: LOG.warning( "Database {} is in quarantine and will be removed".format( self.name ) ) for credential in self.credentials.all(): instance = factory_for(self.databaseinfra) instance.try_remove_user(credential) engine = self.databaseinfra.engine databaseinfra = self.databaseinfra try: DatabaseHistory.objects.create( database_id=self.id, name=self.name, description=self.description, engine='{} {}'.format( engine.engine_type.name, engine.version ), project=self.project.name if self.project else '', team=self.team.name if self.team else '', databaseinfra_name=databaseinfra.name, plan=databaseinfra.plan.name, disk_size_kb=databaseinfra.disk_offering.size_kb, has_persistence=databaseinfra.plan.has_persistence, environment=self.environment.name, created_at=self.created_at ) except Exception as err: LOG.error( ('Error on creating database history for ' '"database {}: {}'.format(self.id, err))) super(Database, self).delete(*args, **kwargs) else: LOG.warning("Putting database {} in quarantine".format(self.name)) self.is_in_quarantine = True self.is_protected = False self.save() if self.credentials.exists(): for credential in self.credentials.all(): new_password = make_db_random_password() new_credential = Credential.objects.get(pk=credential.id) new_credential.password = new_password new_credential.save() instance = factory_for(self.databaseinfra) instance.try_update_user(new_credential)
def status(self, request, pk): """ Status of DB """ try: db = Database.objects.get(pk=pk) databaseinfra = db.databaseinfra factory_for(databaseinfra).check_status() return Response({'status': 'WORKING'}, status='200') except Database.DoesNotExist: return Response({'status': 'Database does not exist.'}, status='404') except Exception as e: return Response( {'status': 'Error. %s (%s)' % (e.message, type(e))}, status='400')
def create_instance(self, databaseinfra): ec2_api = get_ec2_api() reservation = ec2_api.run_instances(settings.EC2_AMI_ID, subnet_id=settings.EC2_SUBNET_ID) i = reservation.instances[0] # due to a bug in boto, I put this call to allow get instance.ip_address while not i.ip_address: LOG.debug('Refresh instances status') time.sleep(1) i.update() LOG.info("Created instance %s", i.ip_address) host = models.Host() host.hostname = i.public_dns_name host.save() instance = models.Instance() instance.address = i.ip_address # instance.address = i.public_dns_name # instance.address = i.dns_name instance.port = factory_for(databaseinfra).default_port instance.databaseinfra = databaseinfra instance.is_active = False instance.is_arbiter = False instance.hostname = host instance.save() return instance
def create_instance(self, databaseinfra): ec2_api = get_ec2_api() reservation = ec2_api.run_instances(settings.EC2_AMI_ID, subnet_id=settings.EC2_SUBNET_ID) i = reservation.instances[0] # due to a bug in boto, I put this call to allow get instance.ip_address while not i.ip_address: LOG.debug('Refresh instances status') time.sleep(1) i.update() LOG.info("Created instance %s", i.ip_address) host = models.Host() host.hostname = i.public_dns_name host.save() instance = models.Instance() instance.address = i.ip_address # instance.address = i.public_dns_name # instance.address = i.dns_name instance.port = factory_for(databaseinfra).default_port instance.databaseinfra = databaseinfra instance.is_active = False instance.is_arbiter = False instance.hostname = host instance.type = models.Instance.VIRTUAL instance.save() return instance
def do(self, workflow_dict): try: if 'databaseinfra' not in workflow_dict \ or 'clone' not in workflow_dict: return False args = get_clone_args( workflow_dict['clone'], workflow_dict['database']) script_name = factory_for( workflow_dict['clone'].databaseinfra).clone() return_code, output = call_script( script_name, working_dir=settings.SCRIPTS_PATH, args=args, split_lines=False,) LOG.info("Script Output: {}".format(output)) LOG.info("Return code: {}".format(return_code)) if return_code != 0: workflow_dict['exceptions']['traceback'].append(output) return False return True except Exception: traceback = full_stack() workflow_dict['exceptions']['error_codes'].append(DBAAS_0017) workflow_dict['exceptions']['traceback'].append(traceback) return False
def do(self, workflow_dict): try: if 'databaseinfra' not in workflow_dict \ or 'clone' not in workflow_dict : return False args = get_clone_args(workflow_dict['clone'], workflow_dict['database']) script_name = factory_for( workflow_dict['clone'].databaseinfra).clone() return_code, output = call_script( script_name, working_dir=settings.SCRIPTS_PATH, args=args, split_lines=False, ) LOG.info("Script Output: {}".format(output)) LOG.info("Return code: {}".format(return_code)) if return_code != 0: workflow_dict['exceptions']['traceback'].append(output) return False return True except Exception: traceback = full_stack() workflow_dict['exceptions']['error_codes'].append(DBAAS_0017) workflow_dict['exceptions']['traceback'].append(traceback) return False
def clean(self, *args, **kwargs): if self.instance_type == self.MONGODB_ARBITER or not self.is_active: # no connection check is needed return LOG.debug('Checking instance %s (%s) status...', self.connection, self.databaseinfra) # self.clean_fields() if not self.databaseinfra.engine_id: raise ValidationError({'engine': _("No engine selected")}) from drivers import factory_for from drivers.errors import GenericDriverError, ConnectionError, \ AuthenticationError try: engine = factory_for(self.databaseinfra) # validate instance connection before saving engine.check_status(instance=self) LOG.debug('Instance %s is ok', self) except AuthenticationError, e: LOG.exception(e) # at django 1.5, model validation throught form doesn't use field name in ValidationError. # I put here, because I expected this problem can be solved in next # versions raise ValidationError({'user': e.message})
def delete(self, *args, **kwargs): if self.is_in_quarantine: LOG.warning( "Database {} is in quarantine and will be removed".format( self.name)) for credential in self.credentials.all(): instance = factory_for(self.databaseinfra) instance.remove_user(credential) engine = self.databaseinfra.engine databaseinfra = self.databaseinfra try: DatabaseHistory.objects.create( database_id=self.id, name=self.name, description=self.description, engine='{} {}'.format(engine.engine_type.name, engine.version), project=self.project.name if self.project else '', team=self.team.name if self.team else '', databaseinfra_name=databaseinfra.name, plan=databaseinfra.plan.name, disk_size_kb=databaseinfra.disk_offering.size_kb, has_persistence=databaseinfra.plan.has_persistence, environment=self.environment.name, created_at=self.created_at) except Exception, err: LOG.error( 'Erro ao criar o database history para "o database {}: {}'. format(self.id, err)) super(Database, self).delete(*args, **kwargs)
def do(self): if not self.is_first_instance: return try: args = get_clone_args(self.step_manager.origin_database, self.database) script_name = factory_for(self.infra).clone() return_code, output = call_script( script_name, working_dir=settings.SCRIPTS_PATH, args=args, split_lines=False) LOG.info("Script Output: {}".format(output)) LOG.info("Return code: {}".format(return_code)) if return_code != 0: raise Exception(output) return False return True except Exception as err: raise Exception(err) return False
def clone_database(self, origin_database, dest_database, user=None): #register History task_history = TaskHistory.register(request=self.request, user=user) LOG.info("origin_database: %s" % origin_database) LOG.info("dest_database: %s" % dest_database) # task_state = self.AsyncResult(self.request.id).state) LOG.info("id: %s | task: %s | kwargs: %s | args: %s" % (self.request.id, self.request.task, self.request.kwargs, str(self.request.args))) args = get_clone_args(origin_database, dest_database) try: script_name = factory_for(origin_database.databaseinfra).clone() #script_name = "dummy_clone.sh" return_code, output = call_script(script_name, working_dir=settings.SCRIPTS_PATH, args=args) LOG.info("%s - return code: %s" % (self.request.id, return_code)) if return_code != 0: task_history.update_status_for(TaskHistory.STATUS_ERROR, details=output) LOG.error("task id %s - error occurred. Transaction rollback" % self.request.id) rollback(dest_database) else: task_history.update_status_for(TaskHistory.STATUS_SUCCESS) except SoftTimeLimitExceeded: LOG.error("task id %s - timeout exceeded" % self.request.id) task_history.update_status_for(TaskHistory.STATUS_ERROR, details="timeout exceeded") except Exception, e: LOG.error("task id %s error: %s" % (self.request.id, e)) task_history.update_status_for(TaskHistory.STATUS_ERROR, details=e)
def create_new_credential(self): """creates a new credential for the database with a random password""" engine = factory_for(self.databaseinfra) LOG.info("creating new credential for database %s" % self.name) credential = Credential(user=Credential.USER_PATTERN % self.name, password=make_db_random_password(), database=self) credential.save() engine.create_user(credential) return credential
def database_pre_delete(sender, **kwargs): """ database pre delete signal. Removes database from the engine """ database = kwargs.get("instance") LOG.debug("database pre-delete triggered") engine = factory_for(database.databaseinfra) engine.remove_database(database)
def status(self, request, pk): """ Status of DB """ try: db = Database.objects.get(pk=pk) databaseinfra = db.databaseinfra factory_for(databaseinfra).check_status() return Response( {'status': 'WORKING'}, status='200') except Database.DoesNotExist: return Response( {'status': 'Database does not exist.'}, status='404') except Exception as e: return Response( {'status': 'Error. %s (%s)' % (e.message, type(e))}, status='400')
def clone_database(self, origin_database, clone_name, user=None): # register History AuditRequest.new_request("clone_database", self.request.kwargs["user"], "localhost") try: task_history = TaskHistory.register(request=self.request, user=user) LOG.info("origin_database: %s" % origin_database) dest_database = Database.objects.get(pk=origin_database.pk) dest_database.name = clone_name dest_database.pk = None task_history.update_details(persist=True, details="Loading Process...") result = make_infra(plan=origin_database.plan, environment=origin_database.environment, name=clone_name, task=task_history) if result['created']==False: if 'exceptions' in result: error = "\n\n".join(": ".join(err) for err in result['exceptions']['error_codes']) traceback = "\n\nException Traceback\n".join(result['exceptions']['traceback']) error = "{}\n{}".format(error, traceback) else: error = "There is not any infra-structure to allocate this database." task_history.update_status_for(TaskHistory.STATUS_ERROR, details=error) return finally: AuditRequest.cleanup_request() dest_database.databaseinfra = result['databaseinfra'] dest_database.save() LOG.info("dest_database: %s" % dest_database) LOG.info("id: %s | task: %s | kwargs: %s | args: %s" % ( self.request.id, self.request.task, self.request.kwargs, str(self.request.args))) try: args = get_clone_args(origin_database, dest_database) script_name = factory_for(origin_database.databaseinfra).clone() return_code, output = call_script(script_name, working_dir=settings.SCRIPTS_PATH, args=args, split_lines=False) LOG.info("%s - return code: %s" % (self.request.id, return_code)) if return_code != 0: task_history.update_status_for(TaskHistory.STATUS_ERROR, details=output + "\nTransaction rollback") LOG.error("task id %s - error occurred. Transaction rollback" % self.request.id) rollback_database(dest_database) else: task_history.update_dbid(db=dest_database) task_history.update_status_for(TaskHistory.STATUS_SUCCESS, details=output) except SoftTimeLimitExceeded: LOG.error("task id %s - timeout exceeded" % self.request.id) task_history.update_status_for(TaskHistory.STATUS_ERROR, details="timeout exceeded") rollback_database(dest_database) except Exception, e: LOG.error("task id %s error: %s" % (self.request.id, e)) task_history.update_status_for(TaskHistory.STATUS_ERROR, details=e) rollback_database(dest_database)
def service_status(request, engine_name=None, engine_version=None, service_name=None): """ To check the status of an databaseinfra, tsuru uses the url /resources/<service_name>/status. If the databaseinfra is ok, this URL should return 204. """ engine = __check_service_availability(engine_name, engine_version) if not engine: return Response(data={"error": "endpoint not available for %s(%s)" % (engine_name, engine_version)}, status=500) data = request.DATA LOG.info("status for service %s" % (service_name)) try: databaseinfra = DatabaseInfra.objects.get(name=service_name) factory_for(databaseinfra).check_status() return Response(data={"status": "ok"}, status=204) except DatabaseInfra.DoesNotExist: LOG.warning("databaseinfra not found for service %s" % (service_name)) return Response(data={"status": "not_found"}, status=404) except Exception, e: return Response(data={"error": "%s" % e}, status=500)
def database_post_save(sender, **kwargs): """ database post save signal. Creates the database in the driver and creates a new credential. """ database = kwargs.get("instance") is_new = kwargs.get("created") LOG.debug("database post-save triggered") if is_new: LOG.info("a new database (%s) were created... provision it in the engine" % (database.name)) engine = factory_for(database.databaseinfra) engine.create_database(database)
def delete(self, *args, **kwargs): if self.is_in_quarantine: LOG.warning("Database %s is in quarantine and will be removed" % self.name) for credential in self.credentials.all(): instance = factory_for(self.databaseinfra) instance.remove_user(credential) super(Database, self).delete(*args, **kwargs) # Call the "real" delete() method. else: LOG.warning("Putting database %s in quarantine" % self.name) self.is_in_quarantine = True self.save() if self.credentials.exists(): for credential in self.credentials.all(): new_password = make_db_random_password() new_credential = Credential.objects.get(pk=credential.id) new_credential.password = new_password new_credential.save() instance = factory_for(self.databaseinfra) instance.update_user(new_credential)
def database_post_save(sender, **kwargs): """ database post save signal. Creates the database in the driver and creates a new credential. """ database = kwargs.get("instance") is_new = kwargs.get("created") LOG.debug("database post-save triggered") if is_new and database.engine_type != 'redis': LOG.info("a new database (%s) were created... provision it in the engine" % ( database.name)) engine = factory_for(database.databaseinfra) engine.create_database(database) database.automatic_create_first_credential()
def delete(self, *args, **kwargs): if self.is_in_quarantine: LOG.warning("Database %s is in quarantine and will be removed" % self.name) for credential in self.credentials.all(): instance = factory_for(self.databaseinfra) instance.remove_user(credential) # Call the "real" delete() method. super(Database, self).delete(*args, **kwargs) else: LOG.warning("Putting database %s in quarantine" % self.name) self.is_in_quarantine = True self.save() if self.credentials.exists(): for credential in self.credentials.all(): new_password = make_db_random_password() new_credential = Credential.objects.get(pk=credential.id) new_credential.password = new_password new_credential.save() instance = factory_for(self.databaseinfra) instance.update_user(new_credential)
def delete(self, *args, **kwargs): if self.is_in_quarantine: LOG.warning( "Database {} is in quarantine and will be removed".format( self.name ) ) for credential in self.credentials.all(): instance = factory_for(self.databaseinfra) instance.remove_user(credential) engine = self.databaseinfra.engine databaseinfra = self.databaseinfra try: DatabaseHistory.objects.create( database_id=self.id, name=self.name, description=self.description, engine='{} {}'.format( engine.engine_type.name, engine.version ), project=self.project.name if self.project else '', team=self.team.name if self.team else '', databaseinfra_name=databaseinfra.name, plan=databaseinfra.plan.name, disk_size_kb=databaseinfra.disk_offering.size_kb, has_persistence=databaseinfra.plan.has_persistence, environment=self.environment.name, created_at=self.created_at ) except Exception, err: LOG.error('Erro ao criar o database history para "o database {}: {}'.format(self.id, err)) super(Database, self).delete(*args, **kwargs)
def __get_engine__(self, credential): return factory_for(credential.database.databaseinfra)
from util import laas #laas.register_database_laas(dest_database) except Exception, e: traceback = full_stack() LOG.error("Ops... something went wrong: %s" % e) LOG.error(traceback) task_history.update_details(persist=True, details='\n' + traceback) LOG.info("id: %s | task: %s | kwargs: %s | args: %s" % ( self.request.id, self.request.task, self.request.kwargs, str(self.request.args))) try: args = get_clone_args(origin_database, dest_database) script_name = factory_for(origin_database.databaseinfra).clone() return_code, output = call_script(script_name, working_dir=settings.SCRIPTS_PATH, args=args, split_lines=False) LOG.info("%s - return code: %s" % (self.request.id, return_code)) if return_code != 0: task_history.update_status_for(TaskHistory.STATUS_ERROR, details=output + "\nTransaction rollback") LOG.error("task id %s - error occurred. Transaction rollback" % self.request.id) rollback_database(dest_database) else: task_history.update_dbid(db=dest_database) task_history.update_status_for(TaskHistory.STATUS_SUCCESS, details=output) except SoftTimeLimitExceeded: LOG.error("task id %s - timeout exceeded" % self.request.id) task_history.update_status_for(TaskHistory.STATUS_ERROR, details="timeout exceeded") rollback_database(dest_database) except Exception, e: LOG.error("task id %s error: %s" % (self.request.id, e))
LOG.info("removing service %s" % (service_name)) # removes database try: database = Database.objects.get(name=service_name) database.delete() except Database.DoesNotExist: LOG.warning("database not found for service %s" % (service_name)) except Exception, e: LOG.error("error removing database %s: %s" % (service_name, e)) return Response(data={"error": "%s" % e}, status=500) # removes databaseinfra try: databaseinfra = DatabaseInfra.objects.get(name=service_name) driver = factory_for(databaseinfra) databaseinfra.delete() return Response(data={"status": "ok"}, status=200) except DatabaseInfra.DoesNotExist: LOG.warning("databaseinfra not found for service %s" % (service_name)) return Response(data={"status": "not_found"}, status=404) except Exception, e: LOG.error("error removing databaseinfra %s: %s" % (service_name, e)) return Response(data={"error": "%s" % e}, status=500) @api_view(["POST"]) @renderer_classes((JSONRenderer, JSONPRenderer)) def service_bind(request, engine_name=None, engine_version=None, service_name=None): """ In the bind action, tsuru calls your service via POST on /resources/<service_name>/ with the "app-hostname"
super(Database, self).delete(*args, **kwargs) else: LOG.warning("Putting database {} in quarantine".format(self.name)) self.is_in_quarantine = True self.is_protected = False self.save() if self.credentials.exists(): for credential in self.credentials.all(): new_password = make_db_random_password() new_credential = Credential.objects.get(pk=credential.id) new_credential.password = new_password new_credential.save() instance = factory_for(self.databaseinfra) instance.update_user(new_credential) def clean(self): if not self.pk: self.name = slugify(self.name) if self.name in self.__get_database_reserved_names(): raise ValidationError( _("{} is a reserved database name".format(self.name))) def automatic_create_first_credential(self): LOG.info("creating new credential for database {}".format(self.name)) user = Credential.USER_PATTERN % self.name credential = Credential.create_new_credential(user, self) return credential
def get_driver(self): import drivers return drivers.factory_for(self)
LOG.info("removing service %s" % (service_name)) #removes database try: database = Database.objects.get(name=service_name) database.delete() except Database.DoesNotExist: LOG.warning("database not found for service %s" % (service_name)) except Exception, e: LOG.error("error removing database %s: %s" % (service_name, e)) return Response(data={"error": "%s" % e}, status=500) #removes databaseinfra try: databaseinfra = DatabaseInfra.objects.get(name=service_name) driver = factory_for(databaseinfra) databaseinfra.delete() return Response(data={"status": "ok"}, status=200) except DatabaseInfra.DoesNotExist: LOG.warning("databaseinfra not found for service %s" % (service_name)) return Response(data={"status": "not_found"}, status=404) except Exception, e: LOG.error("error removing databaseinfra %s: %s" % (service_name, e)) return Response(data={"error": "%s" % e}, status=500) @api_view(['POST']) @renderer_classes((JSONRenderer, JSONPRenderer)) def service_bind(request, engine_name=None, engine_version=None,
def __get_engine__(self, databaseinfra): return factory_for(databaseinfra)
super(Database, self).delete(*args, **kwargs) else: LOG.warning("Putting database {} in quarantine".format(self.name)) self.is_in_quarantine = True self.is_protected = False self.save() if self.credentials.exists(): for credential in self.credentials.all(): new_password = make_db_random_password() new_credential = Credential.objects.get(pk=credential.id) new_credential.password = new_password new_credential.save() instance = factory_for(self.databaseinfra) instance.update_user(new_credential) def clean(self): if not self.pk: self.name = slugify(self.name) if self.name in self.__get_database_reserved_names(): raise ValidationError( _("{} is a reserved database name".format( self.name )) ) def automatic_create_first_credential(self): LOG.info("creating new credential for database {}".format(self.name))
def get_engine(self, database): return factory_for(database.databaseinfra)