func (s *CephProvider) GetSummary(req models.RpcRequest, resp *models.RpcResponse) error { ctxt := req.RpcRequestContext result := make(map[string]interface{}) httpStatusCode := http.StatusOK mon_down_count := 0 monCriticalAlertsCount := 0 var err_str string mons, monErr := GetMons(nil) if monErr != nil { err_str = fmt.Sprintf("Unable to fetch monitor nodes.Error %v", monErr.Error()) logger.Get().Error("%s - Unable to fetch monitor nodes.Error %v", ctxt, monErr.Error()) } else { for _, mon := range mons { monCriticalAlertsCount = monCriticalAlertsCount + mon.AlmCritCount if mon.Status == models.NODE_STATUS_ERROR { mon_down_count = mon_down_count + 1 } } result[models.Monitor] = map[string]int{skyring_monitoring.TOTAL: len(mons), models.STATUS_DOWN: mon_down_count, "criticalAlerts": monCriticalAlertsCount} } var err error result["pgnum"], err = ComputeSystemPGNum() err_str = err_str + fmt.Sprintf("%s", err) if err_str != "" { if len(result) != 0 { httpStatusCode = http.StatusPartialContent } else { httpStatusCode = http.StatusInternalServerError } } objCount, err := ComputeObjectCount(nil) if err != nil { logger.Get().Error("%s - Error fetching the object count. Error %v", ctxt, err) } result["objects"] = objCount bytes, marshalErr := json.Marshal(result) if marshalErr != nil { *resp = utils.WriteResponseWithData(http.StatusInternalServerError, fmt.Sprintf("%s-%s", ctxt, err_str), []byte{}) logger.Get().Error("%s-Failed to marshal %v.Error %v", ctxt, result, marshalErr) return fmt.Errorf("%s-Failed to marshal %v.Error %v", ctxt, result, marshalErr) } *resp = utils.WriteResponseWithData(httpStatusCode, err_str, bytes) return nil }
func (s *CephProvider) GetServiceCount(req models.RpcRequest, resp *models.RpcResponse) error { ctxt := req.RpcRequestContext request := make(map[string]interface{}) if err := json.Unmarshal(req.RpcRequestData, &request); err != nil { logger.Get().Error(fmt.Sprintf("%s-Unbale to parse the Get Service Count request. error: %v", ctxt, err)) *resp = utils.WriteResponse(http.StatusBadRequest, fmt.Sprintf("Unbale to parse the request. error: %v", err)) return err } Hostname := request["hostname"].(string) TotalSluCount := request["totalslu"].(float64) NodeRoles := request["noderoles"] ServiceDetails := make(map[string]interface{}) ServiceCount, err := salt_backend.GetServiceCount(Hostname, ctxt) if err != nil { logger.Get().Error( "%s-Error fetching service count for node: %s. error: %v", ctxt, Hostname, err) *resp = utils.WriteResponse(http.StatusInternalServerError, fmt.Sprintf("Error fetching service count for node %s. error %v", Hostname, err)) return err } for _, role := range NodeRoles.([]interface{}) { switch role.(string) { case strings.ToUpper(bigfin_models.NODE_SERVICE_OSD): SluUp := ServiceCount[bigfin_models.SLU_SERVICE_COUNT] SluDown := int(TotalSluCount) - ServiceCount[bigfin_models.SLU_SERVICE_COUNT] ServiceDetails["slu"] = map[string]int{"up": SluUp, "down": SluDown} case strings.ToUpper(bigfin_models.NODE_SERVICE_MON): ServiceDetails["mon"] = ServiceCount[bigfin_models.MON_SERVICE_COUNT] } } var bytes []byte bytes, err = json.Marshal(ServiceDetails) if err != nil { logger.Get().Error("%s-Unable to marshal the service count details :%s", ctxt, err) *resp = utils.WriteResponse(http.StatusInternalServerError, fmt.Sprintf("Unable to marshal the service count details for node :%s . error %v", Hostname, err)) return err } *resp = utils.WriteResponseWithData(http.StatusOK, "", bytes) return nil }
func (s *CephProvider) MonitorCluster(req models.RpcRequest, resp *models.RpcResponse) error { ctxt := req.RpcRequestContext cluster_id_str, ok := req.RpcRequestVars["cluster-id"] var monnode *models.Node if !ok { logger.Get().Error("%s-Incorrect cluster id: %s", ctxt, cluster_id_str) *resp = utils.WriteResponse(http.StatusBadRequest, fmt.Sprintf("Incorrect cluster id: %s", cluster_id_str)) return fmt.Errorf("Incorrect cluster id: %s", cluster_id_str) } 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.Error: %v", cluster_id_str, err)) return fmt.Errorf("Error parsing the cluster id: %s.Error: %v", cluster_id_str, err) } cluster, err := getCluster(*cluster_id) if err != nil { logger.Get().Error("%s-Unable to get cluster with id %v.Err %v", ctxt, cluster_id, err.Error()) *resp = utils.WriteResponse(http.StatusBadRequest, fmt.Sprintf("Unable to get cluster with id %v.Err %v", cluster_id, err.Error())) return fmt.Errorf("Unable to get cluster with id %v.Err %v", cluster_id, err.Error()) } monnode, err = GetCalamariMonNode(*cluster_id, ctxt) if err != nil { logger.Get().Error("%s-Unable to pick a random mon from cluster %v.Error: %v", ctxt, cluster.Name, err.Error()) *resp = utils.WriteResponse(http.StatusBadRequest, fmt.Sprintf("Unable to pick a random mon from cluster %v.Error: %v", cluster.Name, err.Error())) return fmt.Errorf("Unable to pick a random mon from cluster %v.Error: %v", cluster.Name, err.Error()) } monName := (*monnode).Hostname err = initMonitoringRoutines(ctxt, cluster, monName, MonitoringRoutines) if err != nil { logger.Get().Error("%s-Error: %v", ctxt, err.Error()) *resp = utils.WriteResponse(http.StatusBadRequest, fmt.Sprintf("Error: %v", err.Error())) return fmt.Errorf("Error: %v", err.Error()) } *resp = utils.WriteResponseWithData(http.StatusOK, "", []byte{}) return nil }
func (s *CephProvider) GetStorages(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 } monnode, err := GetCalamariMonNode(*cluster_id, ctxt) if err != nil { logger.Get().Error("%s-Error getting a mon node in cluster: %v. error: %v", ctxt, *cluster_id, err) *resp = utils.WriteResponse(http.StatusInternalServerError, fmt.Sprintf("Error getting a mon node in cluster. error: %v", err)) return err } // Get cluster details sessionCopy := db.GetDatastore().Copy() defer sessionCopy.Close() var cluster models.Cluster coll := sessionCopy.DB(conf.SystemConfig.DBConfig.Database).C(models.COLL_NAME_STORAGE_CLUSTERS) if err := coll.Find(bson.M{"clusterid": *cluster_id}).One(&cluster); err != nil { logger.Get().Error("%s-Error getting details for cluster: %v. error: %v", ctxt, *cluster_id, err) *resp = utils.WriteResponse(http.StatusInternalServerError, fmt.Sprintf("Error getting cluster details. error: %v", err)) return err } // Get the pools for the cluster pools, err := cephapi_backend.GetPools(monnode.Hostname, *cluster_id, ctxt) if err != nil { logger.Get().Error("%s-Error getting storages for cluster: %s. error: %v", ctxt, cluster.Name, err) *resp = utils.WriteResponse(http.StatusInternalServerError, fmt.Sprintf("Error getting storages. error: %v", err)) return err } var storages []models.AddStorageRequest for _, pool := range pools { storage := models.AddStorageRequest{ Name: pool.Name, Replicas: pool.Size, } if pool.QuotaMaxObjects != 0 && pool.QuotaMaxBytes != 0 { storage.QuotaEnabled = true quotaParams := make(map[string]string) quotaParams["quota_max_objects"] = strconv.Itoa(pool.QuotaMaxObjects) quotaParams["quota_max_bytes"] = strconv.FormatUint(pool.QuotaMaxBytes, 10) storage.QuotaParams = quotaParams } options := make(map[string]string) options["id"] = strconv.Itoa(pool.Id) options["pg_num"] = strconv.Itoa(pool.PgNum) options["pgp_num"] = strconv.Itoa(pool.PgpNum) options["full"] = strconv.FormatBool(pool.Full) options["hashpspool"] = strconv.FormatBool(pool.HashPsPool) options["min_size"] = strconv.FormatUint(pool.MinSize, 10) options["crash_replay_interval"] = strconv.Itoa(pool.CrashReplayInterval) options["crush_ruleset"] = strconv.Itoa(pool.CrushRuleSet) // Get EC profile details of pool ok, out, err := cephapi_backend.ExecCmd( monnode.Hostname, *cluster_id, fmt.Sprintf("ceph --cluster %s osd pool get %s erasure_code_profile --format=json", cluster.Name, pool.Name), ctxt) if err != nil || !ok { storage.Type = models.STORAGE_TYPE_REPLICATED logger.Get().Warning("%s-Error getting EC profile details of pool: %s of cluster: %s", ctxt, pool.Name, cluster.Name) } else { var ecprofileDet bigfinmodels.ECProfileDet if err := json.Unmarshal([]byte(out), &ecprofileDet); err != nil { logger.Get().Warning("%s-Error parsing EC profile details of pool: %s of cluster: %s", ctxt, pool.Name, cluster.Name) } else { storage.Type = models.STORAGE_TYPE_ERASURE_CODED options["ecprofile"] = ecprofileDet.ECProfile } } storage.Options = options storages = append(storages, storage) } result, err := json.Marshal(storages) if err != nil { logger.Get().Error("%s-Error forming the output for storage list for cluster: %s. error: %v", ctxt, cluster.Name, 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 }
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 }
func (s *CephProvider) GetDiskHierarchy(req models.RpcRequest, resp *models.RpcResponse) error { var request models.DiskHierarchyRequest ctxt := req.RpcRequestContext if err := json.Unmarshal(req.RpcRequestData, &request); err != nil { logger.Get().Error(fmt.Sprintf("%s-Unbale to parse the disk hierarchy request. error: %v", ctxt, err)) *resp = utils.WriteResponse(http.StatusBadRequest, fmt.Sprintf("Unbale to parse the request. error: %v", err)) return err } if request.JournalSize == "" { request.JournalSize = fmt.Sprintf("%dMB", JOURNALSIZE) } nodes, err := util.GetNodes(request.ClusterNodes) if err != nil { logger.Get().Error( "%s-Error getting nodes list from DB for cluster %s. error: %v", ctxt, request.ClusterName, err) return err } hierarchy := make(map[string]map[string]string) var storageSize float64 for _, requestNode := range request.ClusterNodes { disksMap := make(map[string]string) uuid, err := uuid.Parse(requestNode.NodeId) if err != nil { logger.Get().Error( "%s-Error parsing node id: %s for cluster: %s. error: %v", ctxt, requestNode.NodeId, request.ClusterName, err) continue } devices := make(map[string]models.Disk) storageNode := nodes[*uuid] // Form a map of storage node disks var nodeDisksMap map[string]models.Disk = make(map[string]models.Disk) for _, storageDisk := range storageNode.StorageDisks { nodeDisksMap[storageDisk.Name] = storageDisk } for diskName, storageDisk := range nodeDisksMap { for idx := 0; idx < len(requestNode.Devices); idx++ { if diskName == requestNode.Devices[idx].Name { devices[requestNode.Devices[idx].Name] = storageDisk } } } // Utility function returns value in MB so multiply by 1024 to make is bytes jSize := utils.SizeFromStr(request.JournalSize) * float64(1024) diskWithJournalMapped := getDiskWithJournalMapped(devices, jSize) for disk, journal := range diskWithJournalMapped { disksMap[disk] = journal.JournalDisk for _, storageDisk := range storageNode.StorageDisks { if storageDisk.Name == disk { storageSize += storageDisk.Size } } } hierarchy[requestNode.NodeId] = disksMap } retVal := models.DiskHierarchyDetails{ ClusterName: request.ClusterName, Hierarchy: hierarchy, StorageSize: storageSize, } result, err := json.Marshal(retVal) if err != nil { logger.Get().Error( "%s-Error forming the output for get disk hierarchy of cluster: %s. error: %v", ctxt, request.ClusterName, 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 }
func (s *CephProvider) GetClusterSummary(req models.RpcRequest, resp *models.RpcResponse) error { ctxt := req.RpcRequestContext result := make(map[string]interface{}) httpStatusCode := http.StatusOK cluster_id_str, ok := req.RpcRequestVars["cluster-id"] if !ok { logger.Get().Error("%s - Incorrect cluster id: %s", ctxt, cluster_id_str) *resp = utils.WriteResponse(http.StatusBadRequest, fmt.Sprintf("Incorrect cluster id: %s", cluster_id_str)) return fmt.Errorf("Incorrect cluster id: %s", cluster_id_str) } clusterId, 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.Error: %v", cluster_id_str, err)) return fmt.Errorf("Error parsing the cluster id: %s.Error: %v", cluster_id_str, err) } mon_down_count := 0 monCriticalAlertsCount := 0 mons, monErr := GetMons(bson.M{"clusterid": *clusterId}) var err_str string if monErr != nil { err_str = fmt.Sprintf("Unable to fetch monitor nodes.Error %v", monErr.Error()) logger.Get().Error("%s - Unable to fetch monitor nodes.Error %v", ctxt, monErr.Error()) } else { for _, mon := range mons { monCriticalAlertsCount = monCriticalAlertsCount + mon.AlmCritCount if mon.Status == models.NODE_STATUS_ERROR { mon_down_count = mon_down_count + 1 } } result[models.Monitor] = map[string]int{skyring_monitoring.TOTAL: len(mons), models.STATUS_DOWN: mon_down_count, "criticalAlerts": monCriticalAlertsCount} } cluster, clusterFetchErr := getCluster(*clusterId) if clusterFetchErr != nil { logger.Get().Error("%s - Unable to fetch cluster with id %v. Err %v", ctxt, *clusterId, clusterFetchErr) return fmt.Errorf("%s - Unable to fetch cluster with id %v. Err %v", ctxt, *clusterId, clusterFetchErr) } /* Fetch pg count */ if pgCount, err := ComputeClusterPGNum(cluster, ctxt); err == nil { result["pgnum"] = pgCount } else { err_str = err_str + fmt.Sprintf("%s", err.Error()) } result[bigfin_models.OBJECTS] = ComputeClusterObjectCount(cluster) if err_str != "" { if len(result) != 0 { httpStatusCode = http.StatusPartialContent } else { httpStatusCode = http.StatusInternalServerError } err = fmt.Errorf("%s - %v", ctxt, err_str) } bytes, marshalErr := json.Marshal(result) if marshalErr != nil { logger.Get().Error("%s - Failed to marshal %v.Error %v", ctxt, result, marshalErr) *resp = utils.WriteResponseWithData(http.StatusInternalServerError, err_str, []byte{}) return fmt.Errorf("%s - Failed to marshal %v.Error %v", ctxt, result, marshalErr) } *resp = utils.WriteResponseWithData(httpStatusCode, err_str, bytes) return nil }