ironic multi conductors realization

看ironic的官方文档,通过给不同的node指定不同的driver可以实现使用ironic 部署管理异构的server,奥妙其实在于多conductor,

不同的node使用不同的driver,从而map到不同的conductor上(rpc call的时候也会相应的发到不同的conductor中),来看

topic = pecan.request.rpcapi.get_topic_for(rpc_node)

在ironic/conductor/rpcapi.pu中get_topic_for方法:

ring = self.ring_manager[node.driver]
dest = ring.get_hosts(node.uuid)
return self.topic + "." + dest[0]

其中:ring_manager = hash_ring.HashRingManager()

self.ring_manager[node.driver]调用RingManager中的__getitem__(self, driver_name)方法,返回

self.ring[driver_name], 即

@property
    def ring(self):
        # Hot path, no lock
        if self._hash_rings is not None:
            return self._hash_rings

        with self._lock:
            if self._hash_rings is None:
                rings = self._load_hash_rings()
                self.__class__._hash_rings = rings
            return self._hash_rings

    def _load_hash_rings(self):
        rings = {}
        d2c = self.dbapi.get_active_driver_dict()

        for driver_name, hosts in d2c.iteritems():
            rings[driver_name] = HashRing(hosts)
        return rings

最终通过rings[driver_name] = HashRing(hosts),由driver_name得到一个HashRing,先来看get_active_driver_dict(),再来看HashRing的get_hosts方法返回什么。

get_active_driver_dict()通过sqlalchemy查询数据中的conductors表,得到conductor配置时候所在的host以及该conductor支持的drivers

class Conductor(Base):
    """Represents a conductor service entry."""

    __tablename__ = 'conductors'
    __table_args__ = (
        schema.UniqueConstraint('hostname', name='uniq_conductors0hostname'),
        table_args()
        )
    id = Column(Integer, primary_key=True)
    hostname = Column(String(255), nullable=False)
    drivers = Column(JSONEncodedList)
    online = Column(Boolean, default=True)

查询之后:

 d2c = collections.defaultdict(set)
        for row in result:
            for driver in row['drivers']:
                d2c[driver].add(row['hostname'])
        return d2c

生成driver -> hosts的哈希表,每一个driver对应多个node(多个node使用同一个driver)


再来看HashRing,初始化时候传入一个host列表

for host in hosts:
            key = str(host).encode('utf8')
            key_hash = hashlib.md5(key)
            for p in range(2 ** CONF.hash_partition_exponent):
                key_hash.update(key)
                hashed_key = self._hash2int(key_hash)
                self._host_hashes[hashed_key] = host
        # Gather the (possibly colliding) resulting hashes into a bisectable
        # list.
        self._partitions = sorted(self._host_hashes.keys())


在初始化Ring的时候

elf._host_hashes = {}
        for host in hosts:
            key = str(host).encode('utf8')
            key_hash = hashlib.md5(key)
            for p in range(2 ** CONF.hash_partition_exponent):
                key_hash.update(key)
                hashed_key = self._hash2int(key_hash)
                self._host_hashes[hashed_key] = host
        # Gather the (possibly colliding) resulting hashes into a bisectable
        # list.
        self._partitions = sorted(self._host_hashes.keys())

使用python的commandline看看_host_hashes table实际上是2**5个hashkey到host的映射

>>> key='ding'.encode('utf8')
>>> key_hash=hashlib.md5(key)
>>> key_hash.update(key)
>>> print key_hash
<md5 HASH object @ 0x7fd37197ca30>
>>> print int(key_hash.hexdigest(),16)
112829692254858769854237475965896089339
>>> key_hash.update(key)
>>> print int(key_hash.hexdigest(),16)
328510452650596731730110572716430698878(key差不多这个样子)
测试一下大概_host_hashes的样子是:

{210434336372988548812286100383594081614L: '192.168.1.12', 261341529905210078673684866260045400778L: '192.168.1.12', 323520237514182616212163730681614553619L: '192.168.1.13', 258950754859020420811173881044830400086L: '192.168.1.13', 33690298986936109064829557520707239091L: '192.168.1.12', 334166521183063638501421621663613889942L: '192.168.1.13', 121474934449745677398821877614671543723L: '192.168.1.12', 152336039920782842890743084167801731181L: '192.168.1.13', 193660519265317885493214682164688808777L: '192.168.1.12', 6517729748627730799505962620472763484L: '192.168.1.13', 274217068100375315285543740308286353911L: '192.168.1.13', 157991666289896217762832347933314497307L: '192.168.1.12', 117733835536317852163361767027400996369L: '192.168.1.13', 49230796137512190692836562479246773981L: '192.168.1.13', 165015105211970305330598773763350313205L: '192.168.1.13', 112418604685575404349027279429093348741L: '192.168.1.13', 95871703577230750888370464878643622。。。。。

所以最后给一个uuid的时候根据该uuid生成一个key,使用bisect.bisect,找到其在_partition中的位置,从而拿到对应的host

可能是我理解的还不到位,可能对于容错这种算法有好处,但是。。。可以更简单的解决的吧。。。

















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值