func (s *CephProvider) UpdateStorage(req models.RpcRequest, resp *models.RpcResponse) error { ctxt := req.RpcRequestContext cluster_id_str := req.RpcRequestVars["cluster-id"] cluster_id, err := uuid.Parse(cluster_id_str) if err != nil { logger.Get().Error( "%s - Error parsing the cluster id: %s. error: %v", ctxt, cluster_id_str, err) *resp = utils.WriteResponse( http.StatusBadRequest, fmt.Sprintf( "Error parsing the cluster id: %s", cluster_id_str)) return err } storage_id_str := req.RpcRequestVars["storage-id"] storage_id, err := uuid.Parse(storage_id_str) if err != nil { logger.Get().Error( "%s - Error parsing the storage id: %s. error: %v", ctxt, storage_id_str, err) *resp = utils.WriteResponse( http.StatusBadRequest, fmt.Sprintf( "Error parsing the storage id: %s", storage_id_str)) return err } var request models.AddStorageRequest if err := json.Unmarshal(req.RpcRequestData, &request); err != nil { logger.Get().Error( "%s - Unbale to parse the request. error: %v", ctxt, err) *resp = utils.WriteResponse( http.StatusBadRequest, fmt.Sprintf( "Unbale to parse the request. error: %v", err)) return err } sessionCopy := db.GetDatastore().Copy() defer sessionCopy.Close() coll := sessionCopy.DB(conf.SystemConfig.DBConfig.Database).C(models.COLL_NAME_STORAGE) var storage models.Storage if err := coll.Find(bson.M{"storageid": *storage_id}).One(&storage); err != nil { logger.Get().Error( "%s - Error getting detals of storage: %v on cluster: %v. error: %v", ctxt, *storage_id, *cluster_id, err) *resp = utils.WriteResponse( http.StatusInternalServerError, fmt.Sprintf( "Error getting the details of storage: %v", *storage_id)) return err } id, err := strconv.Atoi(storage.Options["id"]) if err != nil { logger.Get().Error( "%s - Error getting id of the pool: %v of cluster: %v. error: %v", ctxt, *storage_id, *cluster_id, err) *resp = utils.WriteResponse( http.StatusInternalServerError, fmt.Sprintf( "Error getting id of the pool: %v", *storage_id)) return err } asyncTask := func(t *task.Task) { sessionCopy := db.GetDatastore().Copy() defer sessionCopy.Close() coll := sessionCopy.DB(conf.SystemConfig.DBConfig.Database).C(models.COLL_NAME_STORAGE) for { select { case <-t.StopCh: return default: t.UpdateStatus("Started ceph provider pool updation: %v", t.ID) if request.Name != "" && (request.Replicas != 0 || len(request.Options) != 0) { utils.FailTask( fmt.Sprintf( "Invalid mix of fields to update for storage: %v of cluster: %v. "+ "Name change cannot be mixed with other changes.", *storage_id, *cluster_id), fmt.Errorf("%s-Invalid mix of fields to update", ctxt), t) return } for key := range request.Options { if ok := skyring_util.StringInSlice(key, validConfigs); !ok { utils.FailTask( fmt.Sprintf( "Invalid configuration: %s mentioned for storage: %v of cluster: %v", key, *storage_id, *cluster_id), fmt.Errorf("%s-%v", ctxt, err), t) return } } t.UpdateStatus("Getting a radom mon from cluster") monnode, err := GetCalamariMonNode(*cluster_id, ctxt) if err != nil { utils.FailTask( fmt.Sprintf( "Error getting mon node from cluster: %v", *cluster_id), fmt.Errorf("%s-%v", ctxt, err), t) return } var updatedFields = make(map[string]interface{}) if request.Name != "" { updatedFields["name"] = request.Name } if request.Replicas != 0 { updatedFields["size"] = request.Replicas } if request.QuotaEnabled { for key, value := range request.QuotaParams { reqVal, _ := strconv.ParseUint(value, 10, 64) updatedFields[key] = uint64(reqVal) } } else { if request.QuotaParams["quota_max_objects"] == "0" && request.QuotaParams["quota_max_bytes"] == "0" { updatedFields["quota_max_objects"] = 0 updatedFields["quota_max_bytes"] = 0 } } for key, value := range request.Options { reqVal, _ := strconv.ParseUint(value, 10, 32) updatedFields[key] = uint(reqVal) } t.UpdateStatus("Updating pool details") ok, err := cephapi_backend.UpdatePool( monnode.Hostname, *cluster_id, id, updatedFields, ctxt) if err != nil || !ok { utils.FailTask( fmt.Sprintf( "Error setting the configurations for storage: %v on cluster: %v", *storage_id, *cluster_id), fmt.Errorf("%s-%v", ctxt, err), t) return } var filter bson.M = make(map[string]interface{}) var updates bson.M = make(map[string]interface{}) filter["storageid"] = *storage_id filter["clusterid"] = *cluster_id if request.Name != "" { updates["name"] = request.Name } if request.Replicas != 0 { updates["replicas"] = request.Replicas } if request.QuotaEnabled { updates["quotaenabled"] = true params := make(map[string]string) for key, value := range request.QuotaParams { params[key] = string(value) } updates["quotaparams"] = params } else { if request.QuotaParams["quota_max_objects"] == "0" && request.QuotaParams["quota_max_bytes"] == "0" { updates["quotaenabled"] = false updates["quotaparams"] = map[string]string{} } } if value, ok := request.Options["pg_num"]; ok { updates["options.pgp_num"] = value } t.UpdateStatus("Persisting pool updates in DB") if err := coll.Update(filter, bson.M{"$set": updates}); err != nil { utils.FailTask( fmt.Sprintf( "Error updating storage entity: %v of cluster: %v", *storage_id, *cluster_id), fmt.Errorf("%s-%v", ctxt, err), t) } cluster, err := getCluster(*cluster_id) if err != nil { logger.Get().Error("%s - Failed to get details of cluster: %s. error: %v", ctxt, *cluster_id, err) } else { initMonitoringRoutines(ctxt, cluster, (*monnode).Hostname, []interface{}{FetchOSDStats}) UpdatePgNumToSummaries(cluster, ctxt) } if _, ok := updates["name"]; ok { coll := sessionCopy.DB(conf.SystemConfig.DBConfig.Database).C(models.COLL_NAME_BLOCK_DEVICES) if _, err := coll.UpdateAll(filter, bson.M{"$set": bson.M{"storagename": updates["name"]}}); err != nil && err != mgo.ErrNotFound { utils.FailTask( fmt.Sprintf( "Storage name has changed for storage:%v. Error while updating this info for RBDs in cluster:%v", *storage_id, *cluster_id), fmt.Errorf("%s-%v", ctxt, err), t) } } t.UpdateStatus("Success") t.Done(models.TASK_STATUS_SUCCESS) return } } } if taskId, err := bigfin_task.GetTaskManager().Run( bigfin_conf.ProviderName, "CEPH-UpdateStorage", asyncTask, nil, nil, nil); err != nil { logger.Get().Error( "%s-Task creation failed for update storage on cluster: %v. error: %v", ctxt, *cluster_id, err) *resp = utils.WriteResponse( http.StatusInternalServerError, "Task creation failed for storage update") return err } else { *resp = utils.WriteAsyncResponse( taskId, fmt.Sprintf( "Task Created for update storage on cluster: %v", *cluster_id), []byte{}) } return nil }
func (s *CephProvider) GetClusterNodesForImport(req models.RpcRequest, resp *models.RpcResponse) error { ctxt := req.RpcRequestContext bootstrapNode := req.RpcRequestVars["bootstrapnode"] var clusterForImport models.ClusterForImport out, err := cephapi_backend.GetCluster(bootstrapNode, ctxt) if err != nil { logger.Get().Error( "%s-Error getting cluster details. error: %v", ctxt, err) *resp = utils.WriteResponse( http.StatusInternalServerError, "Error getting cluster details") return err } clusterForImport.ClusterName = out.Name clusterForImport.ClusterId = out.Id clusterForImport.Compatible = true nodes, err := cephapi_backend.GetClusterNodes(bootstrapNode, out.Id, ctxt) if err != nil { logger.Get().Error( "%s-Error getting nodes participating in the cluster: %v", ctxt, out.Id) *resp = utils.WriteResponse( http.StatusInternalServerError, "Error getting nodes participating in the cluster") return err } var clusterNodes []models.NodeForImport sessionCopy := db.GetDatastore().Copy() defer sessionCopy.Close() coll := sessionCopy.DB(conf.SystemConfig.DBConfig.Database).C(models.COLL_NAME_STORAGE_NODES) var fetchedNode models.Node for _, node := range nodes { clusterNode := models.NodeForImport{ Name: node.FQDN, } var nodeType []string for _, service := range node.Services { switch service.Type { case bigfin_models.NODE_SERVICE_MON: if ok := skyring_util.StringInSlice(bigfin_models.NODE_SERVICE_MON, nodeType); !ok { nodeType = append(nodeType, bigfin_models.NODE_SERVICE_MON) } case bigfin_models.NODE_SERVICE_OSD: if ok := skyring_util.StringInSlice(bigfin_models.NODE_SERVICE_OSD, nodeType); !ok { nodeType = append(nodeType, bigfin_models.NODE_SERVICE_OSD) } } } clusterNode.Type = nodeType if strings.HasPrefix(bootstrapNode, node.FQDN) { if node.CephVersion != "" && node.CephVersion != "null" { nodeVerStr := fmt.Sprintf( "%s.%s", strings.Split(node.CephVersion, ".")[0], strings.Split(node.CephVersion, ".")[1]) nodeCephVersion, _ := strconv.ParseFloat(nodeVerStr, 64) clusterForImport.Compatible = (nodeCephVersion >= bigfin_conf.ProviderConfig.Provider.CompatVersion) clusterForImport.Version = nodeVerStr } } if err := coll.Find( bson.M{"hostname": node.FQDN}).One(&fetchedNode); err != nil { clusterNode.Found = false } else { clusterNode.Found = true clusterNode.Name = fetchedNode.Hostname } clusterNodes = append(clusterNodes, clusterNode) } clusterForImport.Nodes = clusterNodes result, err := json.Marshal(clusterForImport) if err != nil { logger.Get().Error( "%s-Error forming the output for import cluster nodes. error: %v", ctxt, err) *resp = utils.WriteResponse( http.StatusInternalServerError, fmt.Sprintf( "Error forming the output. error: %v", err)) return err } *resp = utils.WriteResponseWithData(http.StatusOK, "", result) return nil }