Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
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
}
Exemplo n.º 3
0
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
}
Exemplo n.º 4
0
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
}
Exemplo n.º 5
0
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
}
Exemplo n.º 6
0
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
}
Exemplo n.º 7
0
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
}