package manager

import (
    "net/http"
    "github.com/030io/whalefs/manager/volume"
    "os"
    "io/ioutil"
    "strings"
    "strconv"
    "fmt"
    "time"
    "github.com/030io/whalefs/master/api"
    "github.com/030io/whalefs/master"
    "github.com/030io/whalefs/utils/disk"
)

var (
    MaxDiskUsedPercent uint = 99
    HeartbeatDuration time.Duration = time.Second * 5
    ReadOnly bool = false
    DefaultExpires = time.Minute * 30
)

type VolumeManager struct {
    DataDir      string
    Volumes      map[uint64]*volume.Volume
    AdminPort    int
    AdminHost    string
    PublicPort   int
    PublicHost   string
    AdminServer  *http.ServeMux
    PublicServer *http.ServeMux
    Machine      string
    DataCenter   string
    MasterHost   string
    MasterPort   int
}

func NewVolumeManager(dir string) (*VolumeManager, error) {
    f, err := os.OpenFile(dir, os.O_RDWR, 0)
    if os.IsNotExist(err) {
        panic(err)
    } else if os.IsPermission(err) {
        ReadOnly = true
    }
    f.Close()
    vm := new(VolumeManager)
    vm.DataDir = dir
    fileInfos, err := ioutil.ReadDir(dir)
    if err != nil {
        panic(err)
    }
    vm.Volumes = make(map[uint64]*volume.Volume)
    for _, fi := range fileInfos {
        fileName := fi.Name()
        if strings.HasSuffix(fileName, ".data") {
            vid, err := strconv.ParseUint(fileName[:len(fileName) - 5], 10, 64)
            if err != nil {
                panic(err)
            }
            vm.Volumes[vid], err = volume.NewVolume(dir, vid)
            if err != nil {
                panic(err)
            }
        }
    }
    vm.AdminPort = 7800
    vm.AdminHost = "localhost"
    vm.PublicPort = 7900
    vm.PublicHost = "localhost"
    vm.AdminServer = http.NewServeMux()
    vm.PublicServer = http.NewServeMux()
    vm.PublicServer.HandleFunc("/", vm.publicEntry)
    vm.AdminServer.HandleFunc("/", vm.adminEntry)
    vm.MasterHost = "localhost"
    vm.MasterPort = 8888
    return vm, nil
}

func (vm *VolumeManager)Start() {
    go vm.Heartbeat()

    go func() {
        err := http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", vm.AdminPort), vm.AdminServer)
        if err != nil {
            panic(err)
        }
    }()

    err := http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", vm.PublicPort), vm.PublicServer)
    if err != nil {
        panic(err)
    }
}

func (vm *VolumeManager)Stop() {
    for _, v := range vm.Volumes {
        v.Close()
    }
}

func (vm *VolumeManager)Heartbeat() {
    tick := time.NewTicker(HeartbeatDuration)
    defer tick.Stop()
    for {
        vms := new(master.VolumeManagerStatus)
        vms.AdminHost = vm.AdminHost
        vms.AdminPort = vm.AdminPort
        vms.PublicHost = vm.PublicHost
        vms.PublicPort = vm.PublicPort
        vms.Machine = vm.Machine
        vms.DataCenter = vm.Machine
        vms.VStatusList = make([]*master.VolumeStatus, 0, len(vm.Volumes))

        diskUsage, _ := disk.DiskUsage(vm.DataDir)
        vms.DiskSize = diskUsage.Size
        vms.DiskUsed = diskUsage.Used
        vms.DiskFree = diskUsage.Free
        vms.MaxDiskUsed = diskUsage.Size / 100 * uint64(MaxDiskUsedPercent)
        vms.VolumeMaxSize = volume.MaxVolumeSize

        diskUsedPercent := uint(float64(diskUsage.Used) / float64(diskUsage.Size) * 100)
        if ReadOnly || diskUsedPercent >= MaxDiskUsedPercent {
            //禁止所有volume再进行truncate
            volume.MaxVolumeSize = 0
            vms.CanCreateVolume = false
        } else {
            vms.CanCreateVolume = true
        }

        for vid, v := range vm.Volumes {
            vs := new(master.VolumeStatus)
            vs.Id = vid
            vs.DataFileSize = v.GetDatafileSize()
            vs.Writable = !ReadOnly && v.WriteAble
            vs.MaxFreeSpace = v.GetMaxFreeSpace()
            vms.VStatusList = append(vms.VStatusList, vs)
        }

        api.Heartbeat(vm.MasterHost, vm.MasterPort, vms)
        <-tick.C
    }
}

volume_manager.go的更多相关文章

  1. Kubeadm安装Kubernetes环境

    Kubeadm方式号称一键安装部署,很多人也试过并且顺利成功,可到了我这里因为折腾系统问题,倒腾出不少的坑出来. kubeadm好处是自动配置了必要的服务,以及缺省配置了安全的认证,etcd,apis ...

  2. 基于openstack stable queens版本阅读解析

    基于openstack stable queens版本阅读解析 基于 centos7.5 的linux系统 架构 如下所示,为cinder的官方架构说明: 这里写图片描述 各个组件介绍如下: - DB ...

  3. cinder-volume服务上报自己的状态给cinder-scheduler的rpc通信代码分析

    以juno版本为基础,主要从消息的生产者-消费者模型及rpc client/server模型来分析cinder-volume是如何跟cinder-scheduler服务进行rpc通信的 1.cinde ...

  4. kubelet之volume manager源码分析

    kubernetes ceph-csi分析目录导航 基于tag v1.17.4 https://github.com/kubernetes/kubernetes/releases/tag/v1.17. ...

随机推荐

  1. CALayer的属性和使用

    一.CALayer的常用属性 1.@propertyCGPoint position; 图层中心点的位置,类似与UIView的center:用来设置CALayer在父层中的位置:以父层的左上角为原点( ...

  2. Populating Next Right Pointers in Each Node(I and II)

    Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...

  3. WebLogic域配置策略

    WebLogic域配置策略--手动和模板选项,第一部分 域含有BEA WebLogic Server实例的配置信息.它包含有关服务器.集群和机器的配置信息.域还含有关于资源,例如Java数据库连接(J ...

  4. java线程池原理

    在什么情况下使用线程池?     1.单个任务处理的时间比较短     2.将需处理的任务的数量大     使用线程池的好处:     1.减少在创建和销毁线程上所花的时间以及系统资源的开销     ...

  5. Android框架之Volley与Glide

    PS:在看到这个题目的同时,你们估计会想,Volley与Glide怎么拿来一块说呢,他们虽然不是一个框架,但有着相同功能,那就是图片处理方面.首先我们先来看一下什么volley,又什么是glide. ...

  6. Oracle 11g一步步安装详解

    本文所需的安装包都存放在我网盘中,需要的私聊~ 一.安装VMware tools工具(非必须) 1.虚拟机上点击安装 因为我在虚拟机中做的,后面oracle 安装是图形化安装,需要屏幕大一点,不然有些 ...

  7. linux(centos 7)学习之 ~目录下的文件anaconda-ks.cfg

    这个文件是记录安装系统的一些信息 #version=DEVEL # System authorization information auth --enableshadow --passalgo=sh ...

  8. Centos 7安装python3

    纯傻瓜式步骤,保证成功. 下面的操作,按照步骤来就可以了,不要在中途cd 到别的文件目录下,要想查看效果可以用 lsj加上对应的目录,不需要切换进去. 首先不管你当前在哪个目录下,输入以下命令. [r ...

  9. 黄文俊:Serverless小程序后端技术分享

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 黄文俊,现任腾讯云SCF无服务器云函数高级产品经理,多年企业级系统开发和架构工作经验,对企业级存储.容器平台.微服务架构.无服务器计算等领域 ...

  10. C#语言中的XmlSerializer类的XmlSerializer.Deserialize (Stream)方法举例详解

    包含由指定的 XML 文档反序列化 Stream. 命名空间:   System.Xml.Serialization程序集:  System.Xml(位于 System.Xml.dll) 注意: 反序 ...