執行swift-ring-builder的add命令添加裝置到Ring中,與create命令類似,add命令由swift.cli.ringbuilder.Commands類add()函數完成
# swift/cli/ringbuilder.py def add(): #_parse_add_values()解析參數,並返回一個device的列表,然後檢查新添加的device是否在devs列表中, #如果沒有,則通過RingBuild類的add_dev()函數將新的device添加到Ring中 if len(argv) < 5 or len(argv) % 2 != 1: print Commands.add.__doc__.strip() exit(EXIT_ERROR) for new_dev in _parse_add_values(argv[3:]): for dev in builder.devs: if dev is None: continue if dev['ip'] == new_dev['ip'] and \ dev['port'] == new_dev['port'] and \ dev['device'] == new_dev['device']: print 'Device %d already uses %s:%d/%s.' % \ (dev['id'], dev['ip'], dev['port'], dev['device']) print "The on-disk ring builder is unchanged.\n" exit(EXIT_ERROR) dev_id = builder.add_dev(new_dev) print('Device %s with %s weight got id %s' % (format_device(new_dev), new_dev['weight'], dev_id)) builder.save(argv[1]) exit(EXIT_SUCCESS)
最終使用第一步中建立的swift.common.ring.builder.RingBuilder類執行個體的add_dev()函數完成裝置的添加。
# swift/common/ring/builder.pydef add_dev(self, dev): """ 將一個裝置添加到ring裡面去。這個裝置的dict資料至少需要包含以下的索引值(key) ====== =============================================================== id 裝置的唯一編號(類型為整數),如果"id" key在dict中沒有指定,則預設該裝置的id為系統中下一個可用的id號 weight 這個裝置的權重。這個權重值用來暗示會有多少個partition分配到這個裝置上來。 region 裝置所在的region號(類型為整數)。 zone 裝置所在的zone號(類型為整數)。一個partition會被儘可能地發配到分布在不同的(region,zone)的裝置上去。 ip 裝置的ip地址 port 該裝置的tcp連接埠 device 該裝置的名字(譬如,sdb1) meta 中繼資料,用於儲存使用者自訂資料,譬如裝置上線時間,硬體描述,等等 ====== =============================================================== 注意::添加一個裝置不會立即導致rebalance,因為使用者可能想在添加多個裝置之後統一做rebalance """ if 'id' not in dev: dev['id'] = 0 if self.devs: dev['id'] = max(d['id'] for d in self.devs if d) + 1 if dev['id'] < len(self.devs) and self.devs[dev['id']] is not None: raise exceptions.DuplicateDeviceError( 'Duplicate device id: %d' % dev['id']) # Add holes to self.devs to ensure self.devs[dev['id']] will be the dev while dev['id'] >= len(self.devs): self.devs.append(None) dev['weight'] = float(dev['weight']) dev['parts'] = 0 self.devs[dev['id']] = dev #根據裝置的weight計算應該接納的parttion個數 self._set_parts_wanted() self.devs_changed = True self.version += 1 return dev['id']
這個函數先計算所要添加device的ID,ID值可以不是連續的,裝置表中間允許空洞的存在。然後將裝置加入到Ring的裝置表中,最後設定相關flag,devs_changed表示裝置表有變化,需要rebalance。 這個函數返回後,swift.cli.ringbuilder.Commands類的add()函數會再次調用RingBuild類的save()函數,將更新過的Ring資訊寫到builder檔案中去。 到此添加裝置到Ring的步驟完成。