VSM(Virtual Storage Manager) add new osd 代码分析
vsm add new osd 流程
后台获取可用设备
        |
选择可用设备及osd相关信息等
        |
点击add按钮,把准备部署的osd信息添加到需要部署的item列表中
        |
点击submit按钮,添加item列表中的设备到ceph集群中
下面我们分析一下 后台获取可用设备流程,点击add按钮和点击submit按钮后台触发的流程
后台获取可用设备流程 代码分析
选择 Select Server 后 会促发js函数ChangeServer
virtual-storage-manager-2.2.0\source\vsm-dashboard\static\dashboard\js\addosd.js
function ChangeServer(){
	//reset the add osd form
	ResetForm();
	server = Server.Create();
	//Update the upload field post url
	//$formFileUpload.action="/dashboard/vsm/devices-management/add_new_osd2/?service_id="+server.server_id;
	//Update the OSD form data
	PostData("get_available_disks",{"server_id":server.node_id});
}
从ChangeServer通过PostData去获取可用的disks
连接
/dashboard/vsm/devices-management/get_available_disks/
代码:source\vsm-dashboard\vsm_dashboard\dashboards\vsm\devices-management\views.py:get_available_disks
def get_available_disks(request):
    search_opts = json.loads(request.body)
    server_id = search_opts["server_id"]
    ret = vsmapi.get_available_disks(request, search_opts={
                "server_id": server_id
                ,"result_mode":"get_disks",
            })
    disks = ret['disks']
    if disks is None:disks=[]
    disk_data = json.dumps(disks)
    return HttpResponse(disk_data)
在views.py:get_available_disks里,调用source\vsm-dashboard\vsm_dashboard\api\vsm.py:get_available_disks
代码:
source\vsm-dashboard\vsm_dashboard\api\vsm.py:get_available_disks
def get_available_disks(request,  search_opts):
    return vsmclient(request).devices.get_available_disks( search_opts=search_opts)
然后就到vsmclient中的virtual-storage-manager-2.2.0\source\python-vsmclient\vsmclient\v1\devices.py:DeviceManager.get_available_disks
在get_available_disks函数中,会通过rest 请求到vsm-api 里获取可用disk
vsm\vsm\api\v1\devices.py:Controller.get_available_disks
 def get_available_disks(self,req,):
        context = req.environ['vsm.context']
        server_id = req.GET.get('server_id',None)
        body = {'server_id':server_id}
        disk_list = self.scheduler_api.get_available_disks(context, body)
        return {"available_disks":disk_list}
在Controller.get_available_disks 会调用
source\vsm\vsm\scheduler\api.py:API.get_available_disks->source\vsm\vsm\scheduler\rpcapi.py:SchedulerAPI.get_available_disks
    def get_available_disks(self, ctxt, body=None):
        return self.call(ctxt, self.make_msg('get_available_disks', body=body))
这样 vsm-api进程就远程调用scheduler进程的get_available_disks,进入到
source\vsm\vsm\scheduler\manager.py:SchedulerManager.get_available_disks,在这个SchedulerManager.get_available_disks函数中,
1. 首先获取server_id .
2. 根据server_id 去db中查询server的状态。
3. 如果server的状态为Active,再调source\vsm\vsm\agent\rpcapi.py:AgentAPI.get_available_disks
SchedulerManager.get_available_disks 函数
    def get_available_disks(self, context, body):
        server_id = body['server_id']
        server = db.init_node_get_by_id(context,id=server_id)
        status = server['status']
        if status == 'Active':
            res = self._agent_rpcapi.get_available_disks(context,server['host'])
            return res
AgentAPI.get_available_disks函数
    def get_available_disks(self, context, host):
        topic = rpc.queue_get_for(context, self.topic, host)
        res = self.call(context,
                        self.make_msg('get_available_disks'),
                        topic, version='1.0', timeout=6000)
        return res
在AgentAPI.get_available_disks中实现远程调用agent进程get_available_disks,进入到G:\工作\2017年\VSM\code\virtual-storage-manager-2.2.0\source\vsm\vsm\agent\manager.py:AgentManager.get_available_disks
    def get_available_disks(self, context):
        #LOG.info('333333333')
        available_disk_name = self.ceph_driver.get_available_disks(context)
        LOG.info('available_disk_name=====%s'%available_disk_name)
        devices = db.device_get_all_by_service_id(context,self._service_id)
        dev_used_by_ceph = [dev.journal for dev in devices]
        available_disk_info_list = []
        name_by_path_dict = self.ceph_driver.get_disks_name_by_path_dict(available_disk_name)
        name_by_uuid_dict = self.ceph_driver.get_disks_name_by_uuid_dict(available_disk_name)
        for disk in available_disk_name:
            by_path_name = name_by_path_dict.get(disk,'')
            by_uuid_name = name_by_uuid_dict.get(disk,'')
            if not disk in dev_used_by_ceph and not by_path_name in dev_used_by_ceph and not by_uuid_name in dev_used_by_ceph:
                available_disk_info_list.append({'disk_name':disk,
                                                 'by_path':by_path_name,
                                                 'by_uuid':by_uuid_name,})
        LOG.info('available_disk_info_list=====%s'%available_disk_info_list)
        return available_disk_info_list
1.执行“blockdev --report“ 获取块设备
2.去除/dev/sda 这样的裸设备
3.执行“mount -l“ 获取挂载的设备
4.去除挂载的设备
5.执行“pvs --rows" 获取 做了lvm 的设备
6.去除做了lvm 的设备
add_new_osd 页面 add 按钮代码分析
把页面添加osd所需填写的要素填写后,点击add 按钮,触发js CheckOSDForm 函数
virtual-storage-manager-2.2.0\source\vsm-dashboard\static\dashboard\js\addosd.js
function CheckOSDForm(){
	//Check the field is should not null
	if(   $ctrlJournalDevice.value == ""
	   || $ctrlDataDevice.value == ""
	   || $ctrlWeight.value == ""
	   || $ctrlStorageGroup.value == ""){
		showTip("error","The field is marked as '*' should not be empty");
		return  false;
	}
	//Check the device path is avaliable or not
	var path_data = {
		"server_id":Server.Create().node_id,
		"journal_device_path":$ctrlJournalDevice.value,
		"data_device_path":$ctrlDataDevice.value
	}
	//Post the data and check
	//if the check result is successful, add the osd
	PostData("check_device_path",path_data);
}
1.检测device path 是否是可用的disk  的 path
2.如果条件1符合,把刚刚在页填写的要素放到item列表中
3.如果条件1不符合,报错
检测device path 是否是可用的disk 的 path 流程分析
下面我们来分析一下 检测device path 是否是可用的disk 的 path 这个流程
从CheckOSDForm通过PostData去检查设备路径
连接
/dashboard/vsm/devices-management/check_device_path/
代码:
source\vsm-dashboard\vsm_dashboard\dashboards\vsm\devices-management\views.py:check_device_path
def check_device_path(request):
    search_opts = json.loads(request.body)
    server_id = search_opts["server_id"]
    data_device_path = search_opts["data_device_path"]
    journal_device_path = search_opts["journal_device_path"]
    if data_device_path == journal_device_path:
        status_json = {"status":"Failed",'message':'data_device_path and journal_device_path can not be the same hard disk'}
    else:
        ret = vsmapi.get_available_disks(request, search_opts={
                    "server_id": server_id
                    ,"path":[data_device_path,journal_device_path]
                })
        if ret["ret"] == 1 :
            status_json = {"status":"OK"}
        else:
            status_json = {"status":"Failed",'message':ret.get('message')}
    status_data = json.dumps(status_json)
    return HttpResponse(status_data)
在vsm.py:check_device_path里,调用source\vsm-dashboard\vsm_dashboard\api\vsm.py:get_available_disks
代码:
source\vsm-dashboard\vsm_dashboard\api\vsm.py:get_available_disks
def get_available_disks(request,  search_opts):
    return vsmclient(request).devices.get_available_disks( search_opts=search_opts)
然后就到vsmclient中的virtual-storage-manager-2.2.0\source\python-vsmclient\vsmclient\v1\devices.py:DeviceManager.get_available_disks
在get_available_disks函数中,会
1.通过rest 请求到vsm-api 里获取可用disk
2.如果result_mode=get_disks,返回可用的disks(前面所说的获取可用设备流程)
3.如果是path模式,逐一去查询path是否在可用disks的path里。
    def get_available_disks(self, search_opts=None):
        """
        Get a list of available disks
        """
        if search_opts is None:
            search_opts = {}
        qparams = {}
        for opt, val in search_opts.iteritems():
            if val:
                qparams[opt] = val
        query_string = "?%s" % urllib.urlencode(qparams) if qparams else ""
        resp, body = self.api.client.get("/devices/get_available_disks%s" % (query_string))
        body = body.get("available_disks")
        result_mode = search_opts.get('result_mode')
        if result_mode == 'get_disks':
            return {'disks': body}
        ret = {"ret":1}
        message = []
        paths = search_opts.get("path")
        disks = []
        for disk in body:
            disk_name = disk.get('disk_name','')
            by_path = disk.get('by_path','')
            by_uuid = disk.get('by_uuid','')
            if disk_name:
                disks.append(disk_name)
            if by_path:
                disks.append(by_path)
            if by_uuid:
                disks.append(by_uuid)
        if paths:
            unaviable_paths = [path for path in paths if path not in disks]
            if unaviable_paths:
                message.append('There is no %s '%(','.join(unaviable_paths)))
        if message:
            ret = {"ret":0,'message':'.'.join(message)}
        return ret
add_new_osd 页面 submit 按钮代码分析
点击submit按钮,触发js AddOSD() 函数
virtual-storage-manager-2.2.0\source\vsm-dashboard\static\dashboard\js\addosd.js
function AddOSD(){
	var osd_list = [];
	var OSD_Items = $(".osd-item");
    if(OSD_Items.length == 0){
        showTip("error","Please add the OSD");
        return false;
    }
	for(var i=0;i<OSD_Items.length;i++){
		var osd = {
			"server_name":OSD_Items[i].children[1].innerHTML,
			"storage_group_name":OSD_Items[i].children[3].innerHTML,
            "osd_location":OSD_Items[i].children[4].innerHTML,
			"weight":OSD_Items[i].children[2].innerHTML,
			"journal":OSD_Items[i].children[5].innerHTML,
			"data":OSD_Items[i].children[6].innerHTML
		}
		osd_list.push(osd);
	}
	var post_data = {
		"disks":[]
	}
	//generate the server data
	var server_list = []
	for(var i=0;i<osd_list.length;i++){
		var isExsitServer = false;
		for(var j=0;j<server_list.length;j++){
			if(osd_list[i].server_name == server_list[j].server_name){
				isExsitServer = true;
				break;
			}
		}
		if(isExsitServer == false){
			server = {
				"server_name":osd_list[i].server_name,
				"osdinfo":[]
			};
			server_list.push(server)
		}
	}
	//generate the osd data
	for(var i=0;i<osd_list.length;i++){
		for(var j=0;j<server_list.length;j++){
			if(osd_list[i].server_name == server_list[j].server_name){
				var osd = {
					"storage_group_name":osd_list[i].storage_group_name,
                    "osd_location":osd_list[i].osd_location,
            		"weight":osd_list[i].weight,
            		"journal":osd_list[i].journal,
            		"data":osd_list[i].data
				}
				server_list[j].osdinfo.push(osd);
			}
		}
	}
	//exe add osd
    post_data.disks = server_list;
    console.log(post_data);
    PostData("add_new_osd_action",post_data);
}
1.整理osditem中osd和server
2.执行add_new_osd_action
从AddOSD通过PostData去检查设备路径
连接
/dashboard/vsm/devices-management/add_new_osd_action/
代码:
source\vsm-dashboard\vsm_dashboard\dashboards\vsm\devices-management\views.py:add_new_osd_action
from vsm_dashboard.api import vsm as vsmapi
...
def add_new_osd_action(request):
    data = json.loads(request.body)
    print 'data----7777==',data
    #vsmapi.add_new_disks_to_cluster(request,data)
    vsmapi.add_batch_new_disks_to_cluster(request,data)
    status_json = {"status":"OK"}
    status_data = json.dumps(status_json)
    return HttpResponse(status_data)
从views.py 的import的头文件中vsmapi 就是source\vsm-dashboard\vsm_dashboard\api\vsm.py:add_batch_new_disks_to_cluster
def add_batch_new_disks_to_cluster(request, body):
    return vsmclient(request).osds.add_batch_new_disks_to_cluster(body)
然后就到vsmclient中的source\python-vsmclient\vsmclient\v1\osds.py:OsdManager.add_batch_new_disks_to_cluster
    def add_batch_new_disks_to_cluster(self, body):
        """
        :param context:
        :param body: {"disks":[
                                {'server_id':'1','osdinfo':[{'storage_group_id':
                                                            "weight":
                                                            "jounal":
                                                            "data":},{}]},
                                {'server_id':'2','osdinfo':[{'storage_group_id':
                                                            "weight":
                                                            "jounal":
                                                            "data":},{}]},
                            ]
                    }
        :return:
        """
        url = '/osds/add_batch_new_disks_to_cluster'
        return self.api.client.post(url, body=body)
在OsdManager.add_batch_new_disks_to_cluster函数中,会通过rest 请求到vsm-api 里批量添加osd
vsm\vsm\api\v1\osds.py:Controller.add_batch_new_disks_to_cluster
    def add_batch_new_disks_to_cluster(self, req, body):
        context = req.environ['vsm.context']
        LOG.info("batch_osd_add body= %s" % body)
        ret = self.scheduler_api.add_batch_new_disks_to_cluster(context, body)
        LOG.info("batch_osd_add ret= %s" % ret)
        return ret
在Controller.add_batch_new_disks_to_cluster 会调用
source\vsm\vsm\scheduler\api.py:API.add_batch_new_disks_to_cluster->source\vsm\vsm\scheduler\rpcapi.py:SchedulerAPI.add_batch_new_disks_to_cluster
    def add_batch_new_disks_to_cluster(self, ctxt, body=None):
        return self.call(ctxt, self.make_msg('add_batch_new_disks_to_cluster', body=body))
这样 vsm-api进程就远程调用scheduler进程的get_available_disks,进入到
source\vsm\vsm\scheduler\manager.py:SchedulerManager.add_batch_new_disks_to_cluster,在这个SchedulerManager.add_batch_new_disks_to_cluster,
它把获取每一server所需要添加osd ,然后通过调用SchedulerManager.add_new_disks_to_cluster来添加osd
    def add_batch_new_disks_to_cluster(self, context, body):
        """
        :param context:
        :param body: {"disks":[
                                {'server_id':'1','osdinfo':[{'storage_group_id':
                                                            "weight":
                                                            "journal":
                                                            "data":},{}]},
                                {'server_id':'2','osdinfo':[{'storage_group_id':
                                                            "weight":
                                                            "journal":
                                                            "data":},{}]},
                            ]
                    }
        :return:
        """
        disks = body.get('disks',[])
        try:
            for disk_in_same_server in disks:
                self.add_new_disks_to_cluster(context, disk_in_same_server)
        except:
            return {"message":"data error"}
        return {"message": "success"}
    def add_new_disks_to_cluster(self, context, body):
        server_id = body.get('server_id',None)
        server_name = body.get('server_name',None)
        if server_id is not None:
            server = db.init_node_get_by_id(context,id=server_id)
        elif server_name is not None:
            server = db.init_node_get_by_host(context,host=server_name)
        self._agent_rpcapi.add_new_disks_to_cluster(context, body, server['host'])
        new_osd_count = int(server["data_drives_number"]) + len(body['osdinfo'])
        values = {"data_drives_number": new_osd_count}
        self._conductor_rpcapi.init_node_update(context,
                                        server["id"],
                                        values)
在SchedulerManager.add_new_disks_to_cluster中,执行以下操作
1. 到数据库中查询server 信息
2. 调用source\vsm\vsm\agent\rpcapi.py:AgentAPI.add_new_disks_to_cluster,把osd添加到ceph集群
3. 调用source\vsm\vsm\conductor\rpcapi.py:ConductorAPI.init_node_get_cluster_nodes , 更新数据中server的osd个数。
下面我们来分析一下source\vsm\vsm\agent\rpcapi.py:AgentAPI.add_new_disks_to_cluster,把osd添加到ceph集群 部分
    def add_new_disks_to_cluster(self, context, body, host):
        topic = rpc.queue_get_for(context, self.topic, host)
        res = self.call(context,
                        self.make_msg('add_new_disks_to_cluster',
                                      body=body),
                        topic,
                        version='1.0', timeout=6000)
在AgentAPI.add_new_disks_to_cluster,通过同步远程调用vsm-agent进程的add_new_disks_to_cluster,就是调用source\vsm\vsm\agent\manager.py:AgentManager.add_new_disks_to_cluster
    def add_new_disks_to_cluster(self, context, body):
        all_disk = glob.glob('/dev/disk/by-path/*')
        all_disk_name_dict = self.ceph_driver.get_disks_name(context,all_disk)
        for disk in body['osdinfo']:
            for key,value in all_disk_name_dict.items():
                if value == disk['data']:
                    disk['data'] = key
                if value == disk['journal']:
                    disk['journal'] = key
            osd_id = self.add_disk_to_db(context,disk)
            self.osd_add(context,osd_id)
        return True
在这个函数中
1.self.ceph_driver.get_disks_name(context,all_disk)
    执行"ls -l /dev/disk/by-path/*" 命令 获取服务器中的所有块设备放到字典中
    如
    key=/dev/disk/by-path/pci-0000:00:10.0-scsi-0:0:1:0
    value=/dev/sdb
2.比对需要添加的osdinfo列表,把设备转换为/dev/disk/by-path/pci-0000:00:10.0-scsi-0:0:1:0 模式。
3.osd_id = self.add_disk_to_db(context,disk)
    把osd相关内容添加到数据库的osd表中。
4.self.osd_add(context,osd_id) ,下面详细分析
下面我们分析一下osd_add函数流程
    def osd_add(self, context, osd_id):
        return self.ceph_driver.add_osd(context, host_id=None, osd_id_in=osd_id)
它调用的是
source\vsm\vsm\agent\driver.py:CephDriver.add_osd,这个函数执行一下操作
1.如果osd_id_in不为空,到数据中获取osd和host的相关信息
2.添加osd
    1)通过远程调用conductor的host_storage_groups_devices函数获取strg_list
    2)更新initnode 表
    3)执行“ceph osd create” 命令返回ceph集群分配的osdid
    4)更新数据库的crushmap关系
    5)更新ceph集群的curshmap
    6)调用_add_osd函数 在ceph集群中添加osd
       i.获取osd 的path和osd的keyring path
       ii.确保设备data 分区没有被挂载
       iii.对data 分区进行格式化
       iv.把data 目录和journal目录的用户和用户组改为ceph
       v.挂载data分区到osd path中,并把osd path中的目前清空
       vi.更新ceph.conf
       vii. ceph-osd -i $osd_id --mkfs --mmkey
            ceph auth del osd.$osd_id
            ceph auth add osd.$osd_id osd allow * mon allow rwx -i $osd_keyring_pth
            ceph osd crush add osd.$osd_id $weight $osd_location_str
       viii. 启动osd 进程
             ceph osd crush create-or-move osd.$osd_id $weight $osd_location_str
    def add_osd(self, context, host_id, osd_id_in=None):
        if osd_id_in is not None:
            osd_obj = db.osd_get(context, osd_id_in)
            host_obj =  db.init_node_get_by_device_id(context, osd_obj.device_id)
            host_id = host_obj.id
            LOG.info("begin to add osd %s from host %s"%(osd_obj.device_id,host_id))
        LOG.info('start to ceph osd on %s' % host_id)
        strg_list = self._conductor_api.\
            host_storage_groups_devices(context, host_id)
        LOG.info('strg_list %s' % strg_list)
        #added_to_crushmap = False
        osd_cnt = len(strg_list)
        if osd_id_in is not None:
            osd_cnt = 1
        count = 0
        for strg in strg_list:
            if osd_id_in is not None and strg.get("dev_id") != osd_obj.device_id:
                continue
            LOG.info('>> Step 1: start to ceph osd %s' % strg)
            count = count + 1
            if osd_id_in is  None:
                self._conductor_api.init_node_update(context, host_id, {"status": "add_osd %s/%s"%(count,osd_cnt)})
            # Create osd from # ceph osd create
            stdout = utils.execute("ceph",
                                   "osd",
                                   "create",
                                   run_as_root=True)[0]
            osd_id = str(int(stdout))
            LOG.info('   gen osd_id success: %s' % osd_id)
            # step 1 end
            host = strg['host']
            zone = strg['zone']
            #TODO strg['storage_group']
            # stands for the storage_group_name fetch from DB.
            if strg.get('storage_group',None) is None:
                default_storage_group = db.storage_group_get_all(context)[0]
                strg['storage_group'] = default_storage_group['name']
                strg['storage_group_id'] = default_storage_group['id']
            storage_group = strg['storage_group']
            crush_dict = {"root": "vsm",
                          "storage_group": storage_group,
                          "zone": "_".join([zone, storage_group]),
                          "host": "_".join([host, storage_group, zone]),}
            osd_conf_dict = {"host": host,
                             "primary_public_ip": strg['primary_public_ip'],
                             "secondary_public_ip": strg['secondary_public_ip'],
                             "cluster_ip": strg['cluster_ip'],
                             "dev_name": strg['dev_name'],
                             "dev_journal": strg['dev_journal'],
                             "file_system": strg['file_system']}
            osd_state = {}
            osd_state['osd_name'] = 'osd.%s' % osd_id
            osd_state['device_id'] = strg['dev_id']
            osd_state['storage_group_id'] = strg['storage_group_id']
            osd_state['service_id'] = strg['service_id']
            osd_state['cluster_id'] = strg['cluster_id']
            osd_state['state'] = FLAGS.osd_in_up
			# modify by yanghc 2017-03-21
            # the osd_state did nod need set in here,
			# should is the value of osd_state_ref['weight']
            #osd_state['weight'] = 1.0
            osd_state['operation_status'] = FLAGS.vsm_status_present
            osd_state['public_ip'] = strg['secondary_public_ip']
            osd_state['cluster_ip'] = strg['cluster_ip']
            osd_state['deleted'] = 0
            osd_state['zone_id'] = strg['zone_id']
            if osd_id_in is not None:
                osd_state_ref = db.osd_state_update(context,osd_id_in,osd_state)
            else:
                osd_state_ref = self._conductor_api.osd_state_create(context, osd_state)
            osd_state['osd_location'] = osd_state_ref['osd_location']
            osd_state['weight'] = osd_state_ref['weight'] and float(osd_state_ref['weight']) or 1.0
            LOG.info('>> crush_dict  %s' % crush_dict)
            LOG.info('>> osd_conf_dict %s' % osd_conf_dict)
            LOG.info('>> osd_state %s' % osd_state)
            values = {}
            #if not added_to_crushmap:
            #    LOG.info('>> add crushmap ')
            crushmap = self.get_crushmap_json_format()
            types = crushmap.get_all_types()
            types.sort(key=operator.itemgetter('type_id'))
            if self.is_new_storage_group(crush_dict['storage_group']):
                self._crushmap_mgmt.add_storage_group(crush_dict['storage_group'],\
                                                  crush_dict['root'],types=types)
                # zones = db.zone_get_all_not_in_crush(context)
                # for item in zones:
                #     zone_item = item['name'] + '_' + crush_dict['storage_group']
                #     self._crushmap_mgmt.add_zone(zone_item, \
                #                                 crush_dict['storage_group'],types=types)
                #
                if zone == FLAGS.default_zone:
                    self._crushmap_mgmt.add_rule(crush_dict['storage_group'], 'host')
                else:
                    self._crushmap_mgmt.add_rule(crush_dict['storage_group'], 'zone')
                #TODO update rule_id and status in DB
                rule_dict = self.get_crush_rule_dump_by_name(crush_dict['storage_group'])
                LOG.info("rule_dict:%s" % rule_dict)
                values['rule_id'] = rule_dict['rule_id']
            if self.is_new_zone(crush_dict['zone']):
                self._crushmap_mgmt.add_zone(crush_dict['zone'], \
                                             crush_dict['storage_group'], types=types)
            self._crushmap_mgmt.add_host(crush_dict['host'],
                                         crush_dict['zone'], types=types)
            #    added_to_crushmap = True
            #There must be at least 3 hosts in every storage group when the status is "IN"
            zones, hosts = self._conductor_rpcapi.zones_hosts_get_by_storage_group(context, \
                                                        crush_dict['storage_group'])
            #LOG.info("storage group:%s" % crush_dict['storage_group'])
            #LOG.info("zones:%s" % zones)
            #LOG.info("hosts:%s" % hosts)
            #no zone and zone version
            if zones:
                if zones[0] == FLAGS.default_zone:
                    if host not in hosts and len(hosts) >= 2:
                        values['status'] = FLAGS.storage_group_in
                else:
                    if zone not in zones and len(zones) >= 2:
                        values['status'] = FLAGS.storage_group_in 
            if values:
                db.storage_group_update_by_name(context, crush_dict['storage_group'], values)
            # other steps
            LOG.info('>> _add_osd start ')
            self._add_osd(context,
                          osd_id,
                          crush_dict,
                          osd_conf_dict,
                          osd_state)
            try:
                self.run_add_disk_hook(context)
            except:
                LOG.info('run add_disk error')
												
											VSM(Virtual Storage Manager) add new osd 代码分析的更多相关文章
- VSM(Virtual Storage Manager For Ceph)安装教程
		
转载注明出处,陈小跑 http://www.cnblogs.com/chenxianpao/p/5770271.html 一.安装环境 OS:CentOS7.2 VSM:v2.1 released 二 ...
 - LinkedList add remove get 代码分析
		
add void linkLast(E e) { //e 要添加的元素 final Node<E> l = last; // 最后一个元素 final Node<E> newN ...
 - Windows Storage Server 2008 R2 Standard(64位)之ASM(Automated Storage Manager)管理
		
一.服务器管理器之LUN管理 服务器管理器的LUN管理,右键可删除(注意别删了系统分区在的LUN) 二.ASM(Automated Storage Manager) view 高级信息,请不要修改相关 ...
 - eclipse安装ADT插件重启后不显示Android SDK Manager和Android Virtual Device Manager图标的一种解决办法
		
通常安装,搭建安卓环境后,不显示Android SDK Manager和Android Virtual Device Manager ize解决方法:Eclipse ->window->c ...
 - eclipse中调出android sdk manager和android virtual device manager图标
		
有时候在安装ADT插件后,eclipse菜单栏上不会显示android sdk manager和android virtual device manager两个图标, 这个时候,如果安装ADT插件的步 ...
 - ADT后windows菜单未找到Android SDK Manager和Android Virtual Device Manager该解决方案的选择
		
打开今天凌晨ADT准备编译androidproject的时候,突然发现windows菜单下的Android SDK Manager和Android Virtual Device Manager选项不见 ...
 - Virtual Drive Manager V1.3.2(小巧实用的虚拟光驱)绿色版
		
软件名称: Virtual Drive Manager V1.3.2(小巧实用的虚拟光驱)汉化绿色修正版软件语言: 简体中文授权方式: 免费软件运行环境: Win7 / Vista / Win2003 ...
 - 使用 Virtual Machine Manager 管理虚拟机
		
转载自https://www.ibm.com/developerworks/cn/cloud/library/cl-managingvms/ 尽管服务器管理在过去问题重重,但虚拟化管理简化了一些问 ...
 - wifi display代码 分析
		
转自:http://blog.csdn.net/lilian0118/article/details/23168531 这一章中我们来看Wifi Display连接过程的建立,包含P2P的部分和RTS ...
 
随机推荐
- Keepalive VIP 故障
			
前端环境如下: Nginx + Keepalived ( MASTER ) --> node * | | Cisco ASA --> VIP 1.18 | | Nginx + Keepal ...
 - 找不到 org/springframework/dao/support/PersistenceExceptionTranslator
			
如果用的spring2 则原因是缺少spring-dao.jar 如果用的是spring3(我就栽这儿了) 则原因是缺少org.springframework.transaction-3.0.4.R ...
 - python's descriptor
			
[python's descriptor] 1.实现了以下三个方法任意一个的,且作为成员变量存在的对象,就是descriptor. 1)object.__get__(self, instance, o ...
 - 微信图片反防盗链 用js不太成熟的解决方式 仅供参考
			
$("#imgDiv img").each(function () { var img = $(this); var img_src = img.attr("src&qu ...
 - iOS  打印结构体
			
关于OC直接打印结构体,点(CGRect,CGSize,CGPoint,UIOffset)等数据类型,我们完全可以把其转换为OC对象来进项打印调试,而不必对结构体中的成员变量进行打印.就好比我们可以使 ...
 - hdcloud SOA架构
			
SOA是一个范式 多租户技术 一个租户可以是任何一个应用--或者是企业内部应用,或外部应用,它需要有自己的安全的和排他的虚拟计算环境.该环境包含了从存储到用户界面的所有或者某些选定的企业架构层.所 ...
 - orcle clob字段查询
			
select utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(column,2000,1)) from t
 - mount命令使用
			
mount命令是一个很常用的命令,这里介绍两个服务器上之间的挂载 1 配置NFS服务 FTP服务器提供NFS服务,开放具体路径(/home/hadoop)完全控制权限给其他板子.可以将两个板子之间建立 ...
 - 并发编程CAS操作
			
并发编程CAS操作 简介 CAS即compare and swap,中文就是比较并交换 CAS是Java并发包的基石 原理 其实CAS的原理相对来说比较简单.将要被改变的数据和期望的值作比较,当两个值 ...
 - 4.4.4 无锁的对象引用:AtomicReference和AtomicStampedReference
			
AtomicReference 这个类和AtomicInteger非常类似,只是AtomicReference对应普通的对象引用,而AtomicInteger 它是对整数的封装,它的方法如下 对wea ...