backend.fcmservice.PoolService.knownpools()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 7
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
import os
2
import datetime
3
import json
4
from helpers.telegramhelper import sendalert, sendphoto
5
from messaging.schema import MinerSchema, PoolSchema, AvailablePoolSchema, MinerCurrentPoolSchema
6
from messaging.messages import Message, MessageSchema
7
from domain.mining import Miner, Pool, MinerCurrentPool, AvailablePool
8
from domain.rep import PoolRepository
9
import domain.minerpool
10
from backend.fcmcache import CacheKeys
11
import backend.fcmutils as utils
12
13
class ServiceName:
14
    '''names of infrastructure services'''
15
    messagebus = 'rabbit'
16
    cache = 'redis'
17
    database = 'mysql'
18
    email = 'gmail'
19
    telegram = 'telegram'
20
21
class InfrastructureService:
22
    '''configuration for a dependency'''
23
    def __init__(self, name, connection, host, port, user, password):
24
        self.name = name
25
        self.connection = connection
26
        self.host = host
27
        self.port = port
28
        self.user = user
29
        self.password = password
30
31
class BaseService():
32
    '''Every service will share reference to configuration and cache'''
33
    def __init__(self, config, cache):
34
        self.homedirectory = os.path.dirname(__file__)
35
        self.initmessaging()
36
        self.configuration = config
37
        self.cache = cache
38
        #subclass needs to override
39
        self.component = ''
40
41
    def initmessaging(self):
42
        '''start up messaging'''
43
        self._schemamsg = MessageSchema()
44
45
    def getconfigfilename(self, configfilename):
46
        '''get the contents of a config file'''
47
        return os.path.join(self.homedirectory, configfilename)
48
49
    def serialize(self, entity):
50
        '''serialize any entity
51
        only need schema, message class not needed
52
        '''
53
        if isinstance(entity, Miner):
54
            return utils.serialize(entity, MinerSchema())
55
56
        if isinstance(entity, Pool):
57
            return utils.serialize(entity, PoolSchema())
58
        return None
59
60
    def createmessageenvelope(self):
61
        '''create message envelope'''
62
        return Message(timestamp=datetime.datetime.utcnow(), sender=self.component)
63
64
    def serializemessageenvelope(self, msg):
65
        '''serialize message envelope'''
66
        return self._schemamsg.dumps(msg).data
67
68
    def deserializemessageenvelope(self, body):
69
        '''serialize message envelope'''
70
        return self._schemamsg.load(json.loads(utils.safestring(body))).data
71
72
73
class Configuration(object):
74
    def __init__(self, config):
75
        self.__config = config
76
77
    def get(self, key):
78
        if not key in self.__config:
79
            return None
80
        return self.__config[key]
81
82
    def is_enabled(self, key):
83
        lookupkey = '{0}.enabled'.format(key)
84
        if not lookupkey in self.__config:
85
            return False
86
        value = self.__config[lookupkey]
87
        if isinstance(value, str):
88
            return value == 'true' or value == 'True'
89
        return False
90
91
class PoolService(BaseService):
92
    #def __init__(self, configuration, cache):
93
    #    super(PoolService, self).__init__()
94
95
    def get_all_pools(self):
96
        '''configured pools'''
97
        pools = PoolRepository().readpools(self.getconfigfilename('config/pools.conf'))
98
        return pools
99
100
    def findpool(self, minerpool):
101
        '''find a pool in list'''
102
        if minerpool is None:
103
            return None
104
        for pool in self.get_all_pools():
105
            if minerpool.currentpool == pool.url and minerpool.currentworker.startswith(pool.user):
106
                return pool
107
        return None
108
109
    def knownpools(self):
110
        if not self.cache:
111
            return None
112
        dknownpools = self.cache.gethashset(CacheKeys.knownpools)
113
        if dknownpools:
114
            return utils.deserializelist_withschema(AvailablePoolSchema(), list(dknownpools.values()))
115
        return None
116
117
    def getpool(self, miner: Miner):
118
        '''get pool from cache'''
119
        if not self.cache:
120
            return None
121
        valu = self.cache.trygetvaluefromcache(miner.name + '.pool')
122
        if valu is None:
123
            return None
124
        entity = MinerCurrentPool(miner, **utils.deserialize(MinerCurrentPoolSchema(), valu))
125
        return entity
126
127
    def add_pool(self, minerpool: domain.minerpool.MinerPool):
128
        '''see if pool is known or not, then add it'''
129
        knownpool = self.cache.getfromhashset(CacheKeys.knownpools, minerpool.pool.key)
130
        if not knownpool:
131
            val = utils.jsonserialize(AvailablePoolSchema(), minerpool.pool)
132
            self.cache.putinhashset(CacheKeys.knownpools, minerpool.pool.key, val)
133
134
    def putpool(self, pool: Pool):
135
        '''put pool in cache'''
136
        if pool and pool.name:
137
            valu = self.serialize(pool)
138
            self.cache.tryputcache('pool.{0}'.format(pool.name), valu)
139
140
    def update_pool(self, key, pool: AvailablePool):
141
        self.cache.hdel(CacheKeys.knownpools, key)
142
        knownpool = self.cache.getfromhashset(CacheKeys.knownpools, pool.key)
143
        if not knownpool:
144
            val = utils.jsonserialize(AvailablePoolSchema(), pool)
145
            self.cache.putinhashset(CacheKeys.knownpools, pool.key, val)
146
147
    def save_pool(self, pool: Pool):
148
        sch = PoolSchema()
149
        pools = PoolRepository()
150
        pools.add(pool, self.getconfigfilename('config/pools.conf'), sch)
151
152
        #update the known pools
153
        for known in self.knownpools():
154
            if pool.is_same_as(known):
155
                oldkey = known.key
156
                known.named_pool = pool
157
                #this changes the pool key!
158
                known.user = pool.user
159
                #update the known pool (with new key)
160
                self.update_pool(oldkey, known)
161
162
class Telegram(object):
163
    def __init__(self, config, service):
164
        self.configuration = config
165
        self.service = service
166
167
    def sendmessage(self, message):
168
        if self.configuration.is_enabled('telegram'):
169
            sendalert(message, self.service)
170
171
    def sendphoto(self, file_name):
172
        if os.path.isfile(file_name) and os.path.getsize(file_name) > 0:
173
            if self.configuration.is_enabled('telegram'):
174
                sendphoto(file_name, self.service)
175