Example #1
0
    def __init__(self, conf, **kwargs):
        BaseManager.__init__(self, conf)

        self.logger.debug("Entering MySQLServerManager initialization")
        self.controller.generate_context('mysql')
        self.controller.config_clouds({ "mem" : "512", "cpu" : "1" })
        self.config = Configuration(conf)
        self.logger.debug("Leaving MySQLServer initialization")

        # The unique id that is used to start the master/slave
        self.id = 0
Example #2
0
    def __init__(self, conf, **kwargs):
        BaseManager.__init__(self, conf)

        self.logger.debug("Entering MySQLServerManager initialization")

        # default value for mysql volume size
        self.mysql_volume_size = 1024

        #(genc): this is ignored at the moment
        # self.controller.config_clouds({"mem": "512", "cpu": "1"})
        self.root_pass = None
        self.config = Configuration(conf, self.logger)
        self.logger.debug("Leaving MySQLServer initialization")
Example #3
0
class MySQLManager(BaseManager):

    # MySQL Galera node types
    ROLE_MYSQL = 'mysql'  # regular node running a mysqld daemon
    ROLE_GLB   = 'glb'    # load balancer running a glbd daemon

    def __init__(self, conf, **kwargs):
        BaseManager.__init__(self, conf)

        self.logger.debug("Entering MySQLServerManager initialization")

        # default value for mysql volume size
        self.mysql_volume_size = 1024

        #(genc): this is ignored at the moment
        # self.controller.config_clouds({"mem": "512", "cpu": "1"})
        self.root_pass = None
        self.config = Configuration(conf, self.logger)
        self.logger.debug("Leaving MySQLServer initialization")

    def get_service_type(self):
        return 'mysql'

    def get_node_roles(self):
        return [ self.ROLE_MYSQL, self.ROLE_GLB ]

    def get_default_role(self):
        return self.ROLE_MYSQL

    def get_role_sninfo(self, role, cloud):
        if role == self.ROLE_MYSQL:
            return self.get_standard_sninfo_with_volume(
                        role, cloud, 'mysql-%(vm_id)s',
                        self.mysql_volume_size)
        else:
            return BaseManager.get_role_sninfo(self, role, cloud)

    def get_role_logs(self, role):
        logs = BaseManager.get_role_logs(self, role)

        if role == self.ROLE_MYSQL:
            logs.extend([{'filename': 'mysql.log',
                          'description': 'MySQL log',
                          'path': '/var/cache/cpsagent/mysql.log'}]);

        return logs

    def get_context_replacement(self):
        if not self.root_pass:
            # self.root_pass='******'
            self.root_pass = ''.join([choice(string.letters + string.digits) for i in range(10)])
        # self.logger.debug('setting context to %s' % dict(mysql_username='******', mysql_password=self.root_pass))
        return dict(mysql_username='******', mysql_password=str(self.root_pass))

    def on_start(self, nodes):
        succ = self._start_mysqld(nodes)
        self.config.addMySQLServiceNodes(nodes)
        return succ

    def _start_mysqld(self, nodes):
        dev_name = None
        existing_nodes = self.config.get_nodes_addr()
        for serviceNode in nodes:
            try:
                agent.start_mysqld(serviceNode.ip, self.config.AGENT_PORT, existing_nodes, serviceNode.volumes[0].dev_name)
            except AgentException, ex:
                self.logger.exception('Failed to start MySQL node %s: %s' % (str(serviceNode), ex))
                raise
        try:
            glb_nodes = self.config.get_glb_nodes()
            self.logger.debug('MySQL nodes already active: %s' % glb_nodes)
            nodesIp=[]
            nodesIp = ["%s:%s" % (node.ip, self.config.MYSQL_PORT)  # FIXME: find real mysql port instead of default 3306
                         for node in nodes]
            for glb in glb_nodes:
                agent.add_glbd_nodes(glb.ip, self.config.AGENT_PORT, nodesIp)
            return True
        except Exception as ex:
            self.logger.exception('Failed to configure new GLB node: %s' % ex)
            raise
Example #4
0
class MySQLManager(BaseManager):
    """
    Initializes :py:attr:`config` using Config and sets :py:attr:`state` to :py:attr:`S_INIT`

    :param conf: Configuration file.
    :type conf: str
    :type conf: boolean

    """

    def __init__(self, conf, **kwargs):
        BaseManager.__init__(self, conf)

        self.logger.debug("Entering MySQLServerManager initialization")
        self.controller.generate_context('mysql')
        self.controller.config_clouds({ "mem" : "512", "cpu" : "1" })
        self.config = Configuration(conf)
        self.logger.debug("Leaving MySQLServer initialization")

        # The unique id that is used to start the master/slave
        self.id = 0

        self.root_pass = None

    def _do_startup(self, cloud):
        ''' Starts up the service. The first node will be the MYSQL master.
            The next nodes will be slaves to this master. '''

        startCloud = self._init_cloud(cloud)
        #TODO: Get any existing configuration (if the service was stopped and restarted)
        self.logger.debug('do_startup: Going to request one new node')

        # Generate a password for root
        # TODO: send a username?
        self.root_pass = ''.join([choice(string.letters + string.digits) for i in range(10)])
        self.controller.add_context_replacement(dict(mysql_username='******', \
                                mysql_password=self.root_pass),cloud=startCloud)
        try:
            node_instances = self.controller.create_nodes(1,
                                                    client.check_agent_process,
                                                    self.config.AGENT_PORT,
                                                    startCloud)
            self._start_master(node_instances)
            self.config.addMySQLServiceNodes(nodes=node_instances, isMaster=True)
        except:
            self.controller.delete_nodes(node_instances)
            self.logger.exception('do_startup: Failed to request a new node on cloud %s' % cloud)
            self.state = self.S_STOPPED
            return
        self.state = self.S_RUNNING

    def _start_master(self, nodes):
        for serviceNode in nodes:
            try:
                client.create_master(serviceNode.ip, self.config.AGENT_PORT,
                                    self._get_server_id())
            except client.AgentException:
                self.logger.exception('Failed to start MySQL Master at node %s' % str(serviceNode))
                self.state = self.S_ERROR
                raise

    def _start_slave(self, nodes, master):
        slaves = {}
        for serviceNode in nodes:
            slaves[str(self._get_server_id())] = {'ip':serviceNode.ip,
                                                  'port':self.config.AGENT_PORT}
        try:
            self.logger.debug('create_slave for master.ip  = %s' % master)
            client.create_slave(master.ip,
                                self.config.AGENT_PORT, slaves)
        except client.AgentException:
            self.logger.exception('Failed to start MySQL Slave at node %s' % str(serviceNode))
            self.state = self.S_ERROR
            raise

    @expose('GET')
    def list_nodes(self, kwargs):
        """
        HTTP GET method.
        Uses :py:meth:`IaaSClient.listVMs()` to get list of
        all Service nodes. For each service node it gets it
        checks if it is in servers list. If some of them are missing
        they are removed from the list. Returns list of all service nodes.

        :returns: HttpJsonResponse - JSON response with the list of services
        :raises: HttpErrorResponse

        """
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)

        return HttpJsonResponse({
            'masters': [ node.id for node in self.config.getMySQLmasters() ],
            'slaves': [ node.id for node in self.config.getMySQLslaves() ]
            })

    @expose('GET')
    def get_node_info(self, kwargs):
        """
        HTTP GET method. Gets info of a specific node.

        :param param: serviceNodeId is a VMID of an existing service node.
        :type param: str
        :returns: HttpJsonResponse - JSON response with details about the node.
        :raises: ManagerException

        """
        if 'serviceNodeId' not in kwargs:
            return HttpErrorResponse(ManagerException(E_ARGS_MISSING, 'serviceNodeId').message)
        serviceNodeId = kwargs.pop('serviceNodeId')
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)
        if serviceNodeId not in self.config.serviceNodes:
            return HttpErrorResponse(ManagerException(E_ARGS_INVALID , \
                                                      "serviceNodeId" ,\
                                                      detail='Invalid "serviceNodeId"').message)
        serviceNode = self.config.getMySQLNode(serviceNodeId)
        return HttpJsonResponse({
            'serviceNode': {
                            'id': serviceNode.id,
                            'ip': serviceNode.ip,
                            'isMaster': serviceNode.isMaster,
                            'isSlave': serviceNode.isSlave
                            }
            })

    @expose('POST')
    def add_nodes(self, kwargs):
        """
        HTTP POST method. Creates new node and adds it to the list of existing nodes in the manager. Makes internal call to :py:meth:`createServiceNodeThread`.

        :param kwargs: number of nodes to add.
        :type param: str
        :returns: HttpJsonResponse - JSON response with details about the node.
        :raises: ManagerException

        """

        if self.state != self.S_RUNNING:
            return HttpErrorResponse('ERROR: Wrong state to add_nodes')
        if not 'slaves' in kwargs:
            return HttpErrorResponse('ERROR: Required argument doesn\'t exist')
        if not isinstance(kwargs['slaves'], int):
            return HttpErrorResponse('ERROR: Expected an integer value for "count"')
        count = int(kwargs.pop('slaves'))
        self.state = self.S_ADAPTING
        Thread(target=self._do_add_nodes, args=[count, kwargs['cloud']]).start()
        return HttpJsonResponse()

    # TODO: also specify the master for which to add slaves
    def _do_add_nodes(self, count, cloud):
        # Get the master
        masters = self.config.getMySQLmasters()
        startCloud = self._init_cloud(cloud)
        # Configure the nodes as slaves
        #TODO: modify this when multiple masters
        try:
            node_instances = self.controller.create_nodes(count,
                                           client.check_agent_process,
                                           self.config.AGENT_PORT, startCloud)
            for master in masters:
                self._start_slave(node_instances, master)
            self.config.addMySQLServiceNodes(nodes=node_instances, isSlave=True)
        except:
            self.logger.exception('_do_add_nodes: Could not start slave')
            self.state = self.S_ERROR
            return
        self.state = self.S_RUNNING

    def _get_server_id(self):
        self.id = self.id + 1
        return self.id

    @expose('GET')
    def get_service_performance(self, kwargs):
        ''' HTTP GET method. Placeholder for obtaining performance metrics.

        :param kwargs: Additional parameters.
        :type kwargs: dict
        :returns:  HttpJsonResponse -- returns metrics

        '''

        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)
        return HttpJsonResponse({
                'request_rate': 0,
                'error_rate': 0,
                'throughput': 0,
                'response_time': 0,
        })

    @expose('POST')
    def remove_nodes(self, kwargs):
        if self.state != self.S_RUNNING:
            self.logger.debug('Wrong state to remove nodes')
            return HttpErrorResponse('ERROR: Wrong state to remove_nodes')
        if not 'slaves' in kwargs:
            return HttpErrorResponse('ERROR: Required argument doesn\'t exist')
        if not isinstance(kwargs['slaves'], int):
            return HttpErrorResponse('ERROR: Expected an integer value for "count"')
        count = int(kwargs.pop('slaves'))
        if count > len(self.config.getMySQLslaves()):
            return HttpErrorResponse('ERROR: Cannot remove so many nodes')
        self.state = self.S_ADAPTING
        Thread(target=self._do_remove_nodes, args=[count]).start()
        return HttpJsonResponse()

    def _do_remove_nodes(self, count):
        nodes = self.config.getMySQLslaves()[:count]
        self.controller.delete_nodes(nodes)
        self.config.remove_nodes(nodes)
        self.state = self.S_RUNNING
        return HttpJsonResponse()

    @expose('GET')
    def get_service_info(self, kwargs):
        if len(kwargs) != 0:
            return HttpErrorResponse('ERROR: Arguments unexpected')
        return HttpJsonResponse({'state': self.state, 'type': 'mysql'})

    @expose('POST')
    def shutdown(self, kwargs):
        """
        HTTP POST method. Shuts down the manager service.

        :returns: HttpJsonResponse - JSON response with details about the status of a manager node: . ManagerException if something went wrong.
        :raises: ManagerException

        """
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)

        if self.state != self.S_RUNNING:
            return HttpErrorResponse(ManagerException(E_STATE_ERROR).message)

        self.state = self.S_EPILOGUE
        Thread(target=self._do_shutdown, args=[]).start()
        return HttpJsonResponse({'state': self.S_EPILOGUE})


    def _do_shutdown(self):
        ''' Shuts down the service. '''
        #self._stop_slaves( config.getProxyServiceNodes())
        #self._stop_masters(config, config.getWebServiceNodes())
        self.controller.delete_nodes(self.config.serviceNodes.values())
        self.config.serviceNodes = {}
        self.state = self.S_STOPPED

    @expose('GET')
    def get_password(self, kwargs):
        if len(kwargs) != 0:
            return HttpErrorResponse('ERROR: Arguments unexpected')
        return HttpJsonResponse(self.root_pass)

    @expose('POST')
    def set_password(self, kwargs):
        self.logger.debug('Setting password')
        if self.state != self.S_RUNNING:
            self.logger.debug('Service not runnning')
            return HttpErrorResponse('ERROR: Service not running')
        if not 'user' in kwargs:
            return HttpErrorResponse('ERROR: Required argument \'user\' doesn\'t exist')
        if not 'password' in kwargs:
            return HttpErrorResponse('ERROR: Required argument \'password\' doesn\'t exist')

        # Get the master
        masters = self.config.getMySQLmasters()

        #TODO: modify this when multiple masters
        try:
            for master in masters:
                client.set_password(master.ip, self.config.AGENT_PORT, kwargs['user'], kwargs['password'])
        except:
            e = sys.exc_info()[1]
            self.logger.exception('set_password: Could not set password: %s' % e)
            self.state = self.S_ERROR
            return HttpErrorResponse('Failed to set password')
        else:
            self.root_pass = kwargs['password']
            return HttpJsonResponse()

    @expose('GET')
    def sqldump(self, kwargs):
        if self.state != self.S_RUNNING:
            return HttpErrorResponse('ERROR: Wrong state to call sqldump')

        master_ip = self.config.getMySQLmasters()[0].ip
        cmd = 'mysqldump -u mysqldb -h %s --password=%s -A' % (master_ip,
                self.root_pass)
        out, err = run_cmd(cmd)

        if err:
            return HttpErrorResponse(err)

        return HttpJsonResponse(out)

    @expose('UPLOAD')
    def load_dump(self, kwargs):
        self.logger.debug('Uploading mysql dump')
        if 'mysqldump_file' not in kwargs:
            return HttpErrorResponse(ManagerException(ManagerException.E_ARGS_MISSING, \
                                                                     'mysqldump_file').message)
        mysqldump_file = kwargs.pop('mysqldump_file')
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(ManagerException.E_ARGS_UNEXPECTED, \
                                               detail='invalid number of arguments ').message)
        if not isinstance(mysqldump_file, FileUploadField):
            return HttpErrorResponse(ManagerException(ManagerException.E_ARGS_INVALID, \
                                               detail='mysqldump_file should be a file').message)
        fd, filename = tempfile.mkstemp(dir='/tmp')
        fd = os.fdopen(fd, 'w')
        upload = mysqldump_file.file
        bytes = upload.read(2048)
        while len(bytes) != 0:
            fd.write(bytes)
            bytes = upload.read(2048)
        fd.close()

        # Get master
        # TODO: modify this when multiple masters
        masters = self.config.getMySQLmasters()
        try:
            for master in masters:
                client.load_dump(master.ip, self.config.AGENT_PORT, filename)
        except:
            self.logger.exception('load_dump: could not upload mysqldump_file ')
            self.state = self.S_ERROR
            return
        return HttpJsonResponse()
Example #5
0
class MySQLManager(BaseManager):
    """
    Initializes :py:attr:`config` using Config and sets :py:attr:`state` to :py:attr:`S_INIT`

    :param conf: Configuration file.
    :type conf: str
    :type conf: boolean

    """

    def __init__(self, conf, **kwargs):
        BaseManager.__init__(self, conf)

        self.logger.debug("Entering MySQLServerManager initialization")
        self.controller.generate_context('mysql')
        self.controller.config_clouds({ "mem" : "512", "cpu" : "1" })
        self.config = Configuration(conf)
        self.logger.debug("Leaving MySQLServer initialization")

        # The unique id that is used to start the master/slave
        self.id = 0

        self.root_pass = None

    def _do_startup(self, cloud):
        ''' Starts up the service. The first node will be the MYSQL master.
            The next nodes will be slaves to this master. '''

        startCloud = self._init_cloud(cloud)
        #TODO: Get any existing configuration (if the service was stopped and restarted)
        self.logger.debug('do_startup: Going to request one new node')

        # Generate a password for root
        # TODO: send a username?
        self.root_pass = ''.join([choice(string.letters + string.digits) for i in range(10)])
        self.controller.add_context_replacement(dict(mysql_username='******', \
                                mysql_password=self.root_pass),cloud=startCloud)
        try:
            node_instances = self.controller.create_nodes(1,
                                                    client.check_agent_process,
                                                    self.config.AGENT_PORT,
                                                    startCloud)
            self._start_master(node_instances)
            self.config.addMySQLServiceNodes(nodes=node_instances, isMaster=True)
        except:
            self.logger.exception('do_startup: Failed to request a new node on cloud %s' % cloud)
            self.state = self.S_STOPPED
            return
        self.state = self.S_RUNNING

    def _start_master(self, nodes):
        for serviceNode in nodes:
            try:
                client.create_master(serviceNode.ip, self.config.AGENT_PORT,
                                    self._get_server_id())
            except client.AgentException:
                self.logger.exception('Failed to start MySQL Master at node %s' % str(serviceNode))
                self.state = self.S_ERROR
                raise

    def _start_slave(self, nodes, master):
        slaves = {}
        for serviceNode in nodes:
            slaves[str(self._get_server_id())] = {'ip':serviceNode.ip,
                                                  'port':self.config.AGENT_PORT}
        try:
            self.logger.debug('create_slave for master.ip  = %s' % master)
            client.create_slave(master.ip,
                                self.config.AGENT_PORT, slaves)
        except client.AgentException:
            self.logger.exception('Failed to start MySQL Slave at node %s' % str(serviceNode))
            self.state = self.S_ERROR
            raise

    @expose('GET')
    def list_nodes(self, kwargs):
        """
        HTTP GET method.
        Uses :py:meth:`IaaSClient.listVMs()` to get list of
        all Service nodes. For each service node it gets it
        checks if it is in servers list. If some of them are missing
        they are removed from the list. Returns list of all service nodes.

        :returns: HttpJsonResponse - JSON response with the list of services
        :raises: HttpErrorResponse

        """
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)

        return HttpJsonResponse({
            'masters': [ node.id for node in self.config.getMySQLmasters() ],
            'slaves': [ node.id for node in self.config.getMySQLslaves() ]
            })

    @expose('GET')
    def get_node_info(self, kwargs):
        """
        HTTP GET method. Gets info of a specific node.

        :param param: serviceNodeId is a VMID of an existing service node.
        :type param: str
        :returns: HttpJsonResponse - JSON response with details about the node.
        :raises: ManagerException

        """
        if 'serviceNodeId' not in kwargs:
            return HttpErrorResponse(ManagerException(E_ARGS_MISSING, 'serviceNodeId').message)
        serviceNodeId = kwargs.pop('serviceNodeId')
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)
        if serviceNodeId not in self.config.serviceNodes:
            return HttpErrorResponse(ManagerException(E_ARGS_INVALID , \
                                                      "serviceNodeId" ,\
                                                      detail='Invalid "serviceNodeId"').message)
        serviceNode = self.config.getMySQLNode(serviceNodeId)
        return HttpJsonResponse({
            'serviceNode': {
                            'id': serviceNode.id,
                            'ip': serviceNode.ip,
                            'isMaster': serviceNode.isMaster,
                            'isSlave': serviceNode.isSlave
                            }
            })

    @expose('POST')
    def add_nodes(self, kwargs):
        """
        HTTP POST method. Creates new node and adds it to the list of existing nodes in the manager. Makes internal call to :py:meth:`createServiceNodeThread`.

        :param kwargs: number of nodes to add.
        :type param: str
        :returns: HttpJsonResponse - JSON response with details about the node.
        :raises: ManagerException

        """

        if self.state != self.S_RUNNING:
            return HttpErrorResponse('ERROR: Wrong state to add_nodes')
        if not 'slaves' in kwargs:
            return HttpErrorResponse('ERROR: Required argument doesn\'t exist')
        if not isinstance(kwargs['slaves'], int):
            return HttpErrorResponse('ERROR: Expected an integer value for "count"')
        count = int(kwargs.pop('slaves'))
        self.state = self.S_ADAPTING
        Thread(target=self._do_add_nodes, args=[count, kwargs['cloud']]).start()
        return HttpJsonResponse()

    # TODO: also specify the master for which to add slaves
    def _do_add_nodes(self, count, cloud):
        # Get the master
        masters = self.config.getMySQLmasters()
        startCloud = self._init_cloud(cloud)
        # Configure the nodes as slaves
        #TODO: modify this when multiple masters
        try:
            node_instances = self.controller.create_nodes(count,
                                           client.check_agent_process,
                                           self.config.AGENT_PORT, startCloud)
            for master in masters:
                self._start_slave(node_instances, master)
            self.config.addMySQLServiceNodes(nodes=node_instances, isSlave=True)
        except:
            self.logger.exception('_do_add_nodes: Could not start slave')
            self.state = self.S_ERROR
            return
        self.state = self.S_RUNNING

    def _get_server_id(self):
        self.id = self.id + 1
        return self.id

    @expose('GET')
    def get_service_performance(self, kwargs):
        ''' HTTP GET method. Placeholder for obtaining performance metrics.

        :param kwargs: Additional parameters.
        :type kwargs: dict
        :returns:  HttpJsonResponse -- returns metrics

        '''

        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)
        return HttpJsonResponse({
                'request_rate': 0,
                'error_rate': 0,
                'throughput': 0,
                'response_time': 0,
        })

    @expose('POST')
    def remove_nodes(self, kwargs):
        if self.state != self.S_RUNNING:
            self.logger.debug('Wrong state to remove nodes')
            return HttpErrorResponse('ERROR: Wrong state to remove_nodes')
        if not 'slaves' in kwargs:
            return HttpErrorResponse('ERROR: Required argument doesn\'t exist')
        if not isinstance(kwargs['slaves'], int):
            return HttpErrorResponse('ERROR: Expected an integer value for "count"')
        count = int(kwargs.pop('slaves'))
        if count > len(self.config.getMySQLslaves()):
            return HttpErrorResponse('ERROR: Cannot remove so many nodes')
        self.state = self.S_ADAPTING
        Thread(target=self._do_remove_nodes, args=[count]).start()
        return HttpJsonResponse()

    def _do_remove_nodes(self, count):
        nodes = self.config.getMySQLslaves()[:count]
        self.controller.delete_nodes(nodes)
        self.config.remove_nodes(nodes)
        self.state = self.S_RUNNING
        return HttpJsonResponse()

    @expose('GET')
    def get_service_info(self, kwargs):
        if len(kwargs) != 0:
            return HttpErrorResponse('ERROR: Arguments unexpected')
        return HttpJsonResponse({'state': self.state, 'type': 'mysql'})

    @expose('POST')
    def shutdown(self, kwargs):
        """
        HTTP POST method. Shuts down the manager service.

        :returns: HttpJsonResponse - JSON response with details about the status of a manager node: . ManagerException if something went wrong.
        :raises: ManagerException

        """
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(E_ARGS_UNEXPECTED, kwargs.keys()).message)

        if self.state != self.S_RUNNING:
            return HttpErrorResponse(ManagerException(E_STATE_ERROR).message)

        self.state = self.S_EPILOGUE
        Thread(target=self._do_shutdown, args=[]).start()
        return HttpJsonResponse({'state': self.S_EPILOGUE})


    def _do_shutdown(self):
        ''' Shuts down the service. '''
        #self._stop_slaves( config.getProxyServiceNodes())
        #self._stop_masters(config, config.getWebServiceNodes())
        self.controller.delete_nodes(self.config.serviceNodes.values())
        self.config.serviceNodes = {}
        self.state = self.S_STOPPED

    @expose('GET')
    def get_password(self, kwargs):
        if len(kwargs) != 0:
            return HttpErrorResponse('ERROR: Arguments unexpected')
        return HttpJsonResponse(self.root_pass)

    @expose('POST')
    def set_password(self, kwargs):
        self.logger.debug('Setting password')
        if self.state != self.S_RUNNING:
            self.logger.debug('Service not runnning')
            return HttpErrorResponse('ERROR: Service not running')
        if not 'user' in kwargs:
            return HttpErrorResponse('ERROR: Required argument \'user\' doesn\'t exist')
        if not 'password' in kwargs:
            return HttpErrorResponse('ERROR: Required argument \'password\' doesn\'t exist')

        # Get the master
        masters = self.config.getMySQLmasters()

        #TODO: modify this when multiple masters
        try:
            for master in masters:
                client.set_password(master.ip, self.config.AGENT_PORT, kwargs['user'], kwargs['password'])
        except:
            e = sys.exc_info()[1]
            self.logger.exception('set_password: Could not set password: %s' % e)
            self.state = self.S_ERROR
            return HttpErrorResponse('Failed to set password')
        else:
            self.root_pass = kwargs['password']
            return HttpJsonResponse()

    @expose('GET')
    def sqldump(self, kwargs):
        if self.state != self.S_RUNNING:
            return HttpErrorResponse('ERROR: Wrong state to call sqldump')

        master_ip = self.config.getMySQLmasters()[0].ip
        cmd = 'mysqldump -u mysqldb -h %s --password=%s -A' % (master_ip,
                self.root_pass)
        out, err = run_cmd(cmd)

        if err:
            return HttpErrorResponse(err)

        return HttpJsonResponse(out)

    @expose('UPLOAD')
    def load_dump(self, kwargs):
        self.logger.debug('Uploading mysql dump')
        if 'mysqldump_file' not in kwargs:
            return HttpErrorResponse(ManagerException(ManagerException.E_ARGS_MISSING, \
                                                                     'mysqldump_file').message)
        mysqldump_file = kwargs.pop('mysqldump_file')
        if len(kwargs) != 0:
            return HttpErrorResponse(ManagerException(ManagerException.E_ARGS_UNEXPECTED, \
                                               detail='invalid number of arguments ').message)
        if not isinstance(mysqldump_file, FileUploadField):
            return HttpErrorResponse(ManagerException(ManagerException.E_ARGS_INVALID, \
                                               detail='mysqldump_file should be a file').message)
        fd, filename = tempfile.mkstemp(dir='/tmp')
        fd = os.fdopen(fd, 'w')
        upload = mysqldump_file.file
        bytes = upload.read(2048)
        while len(bytes) != 0:
            fd.write(bytes)
            bytes = upload.read(2048)
        fd.close()

        # Get master
        # TODO: modify this when multiple masters
        masters = self.config.getMySQLmasters()
        try:
            for master in masters:
                client.load_dump(master.ip, self.config.AGENT_PORT, filename)
        except:
            self.logger.exception('load_dump: could not upload mysqldump_file ')
            self.state = self.S_ERROR
            return
        return HttpJsonResponse()