Diseño procedimental

En este apartado se referencian los algoritmos implementados en el sistema que son considerados de mayor relevancia.

Envío del comando de creación

extern "C" int createdirectory(const char* home, int uid, int gid, const char* address_host){
    rapidjson::Value Command(rapidjson::kStringType);
    Command.SetString("Create-Home");
    writer.AddMember("Command", Command, allocator);

    char aux[BUFFSIZE];

    int len = sprintf(aux, "%s,%d,%d", home, uid, gid);
    char aux2[len];
    strcpy(aux2, aux);

    rapidjson::Value Params(rapidjson::kStringType);
    Params.SetString(aux2,len);
    writer.AddMember("Params", Params, allocator);

    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> salida(buffer);
    writer.Accept(salida);
    SSL_write(ssl, data_arr, sizeof(data_arr));
    char buf_recv[500];
    len = SSL_read(ssl, buf_recv, sizeof(buf_recv));

extern "C" int create_polo_directories(const char* home, int uid, int gid){

    std::vector<Node> nodes;
    Marco marco(TIMEOUT);
    marco.request_for(nodes, "polousers");

    for (unsigned int i = 0; i < nodes.size(); i++)
    {
        createdirectory(home, uid, gid, nodes[i].getAddress().c_str());
    }
    return 0;
}

Recepción del comando de creación

    def dataReceived(self, data):
        """
        Process a new stream of information

        :param bytes data: The stream of information
        """
        data_dict = json.loads(data.decode('utf-8'))
        #The parameters must be separated by commas
        params = data_dict["Params"].split(',',3)
        if data_dict["Command"] == "Create-Home":
            """The response is acknowledged as soon as possible in order
             to avoid a long waiting time in the requesting node
            """
            self.transport.write(json.dumps({"OK":0}).encode('utf-8'))
            
            logging.debug("I shall now create the directory %s for %d %d with the utmost pleasure" % (params[0], int(params[1]), int(params[2])))
            
            retval = self.create_homedir(params[0], int(params[1]), int(params[2]))
            logging.debug(os.path.join(params[0], 'apache-tomcat-7.0.62'))
            if os.path.exists(os.path.join(params[0], 'apache-tomcat-7.0.62')):
                logging.debug("I shall now configure Tomcat")
                try:
                    self.configure_tomcat(os.path.join(params[0], 'apache-tomcat-7.0.62'), int(params[1]))
                except Exception as e:
                    logging.debug(e)
                    #self.transport.write(json.dumps({"Error":str(e)}).encode('utf-8'))
            if retval == 0:
                logging.debug("Created")
            if retval == 1:
                logging.debug("The directory was not created because it already exists")
        else:
            # Wrong command
            self.transport.write(json.dumps({"Error":1}).encode('utf-8'))

    def create_homedir(self, name, uid, gid):
        """
        Creates the home directory, setting the appropriate permissions
        
        :param str name: The path of the directory

        :param int uid: The uid of the owner

        :param int gid: The gid of the owner's main group
        """
        if os.path.exists(name):
            logging.info("The directory %s already exists.", name)
            return 1

        try:
            shutil.copytree(skeldir, name)
        except OSError as e:
            if e.errno == errno.ENOTDIR:
                shutil.copy(src, name)
            else:
                logging.error("Directory not copied. Error %s" % e)
                return 2

        try:
            for root, dirs, files in os.walk(name):
                for d in dirs: os.chown(os.path.join(root, d), uid, gid)
                for f in files: os.chown(os.path.join(root, f), uid, gid)
        except Exception as e:
            logging.error("Something went wrong during chown. %s" % e)
            return 2

        try:
            os.chown(name, uid, gid)
        except OSError as e:
            logging.error("Ownership could not be set: %s", e)
            return 2

        try:
            os.chmod(name, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
        except OSError as e:
            logging.error("Permission could not be set: %s", e)
            return 0

        return 0

Configuración de Tomcat

    def configure_tomcat(self, directory, uid):
        """
        Configures the local instance of Tomcat to work with a set of ports dedicated to the user.

        Tomcat uses the following ports:

        - 8080: The main port where services listen for connections. It is replaced by uid + 10000 
        - 8005: The shutdown port. It is replaced by uid + 20000

        :param str directory: The path of the Tomcat installation

        :param int uid: The uid of the user, which determines the number of the port
        """
        if not isinstance(uid, six.integer_types):
            error = None
            try:
                uid = int(uid, 10)
            except ValueError:
                error = True

            if error:
                raise Exception("Wrong uid value")

        server_xml = os.path.join(directory, 'conf/server.xml')
        logging.debug(server_xml)
        if not os.path.isfile(server_xml):
            raise Exception("Not found!")
        error = None
        
        try:
            tree = ET.parse(server_xml)
        except Exception:
            error = True
        if error:
            raise Exception("Error on parsing")

        root = tree.getroot()

        root.attrib["port"] = str(uid+conf.STOP_PORT_INCREMENT)

        ajp = root.find("./Service[@name='Catalina']/Connector[@protocol='AJP/1.3']")
        http = root.find("./Service[@name='Catalina']/Connector[@protocol='HTTP/1.1']")
        
        if http is None or ajp is None:
            raise Exception("Necessary tags elements not found in XML")
        
        http.attrib["port"] = str(uid)
        ajp.attrib["port"] = str(uid+conf.MAIN_PORT_INCREMENT)

        tree.write(server_xml)