diff --git a/confluent_server/confluent/discovery/handlers/cpstorage.py b/confluent_server/confluent/discovery/handlers/cpstorage.py index 5403b0b7..419c4dd2 100644 --- a/confluent_server/confluent/discovery/handlers/cpstorage.py +++ b/confluent_server/confluent/discovery/handlers/cpstorage.py @@ -13,7 +13,6 @@ # limitations under the License. import confluent.discovery.handlers.bmc as bmchandler -import eventlet import confluent.util as util try: from urllib import urlencode @@ -34,13 +33,13 @@ class NodeHandler(bmchandler.NodeHandler): fprint = util.get_fingerprint(self.https_cert) return util.cert_matches(fprint, certificate) - def get_webclient(self, user, passwd, newuser, newpass): + async def get_webclient(self, user, passwd, newuser, newpass): wc = webclient.WebConnection(self.ipaddr, 443, verifycallback=self.validate_cert) - wc.connect() + await wc.connect() authdata = urlencode({'username': user, 'password': passwd, 'weblogsign': 1}) - res = wc.grab_json_response_with_status('/api/session', authdata) + res = await wc.grab_json_response_with_status('/api/session', authdata) if res[1] == 200: if res[0].get('force_password', 1) == 0: # Need to handle password change @@ -52,12 +51,12 @@ class NodeHandler(bmchandler.NodeHandler): 'privilege': 4, } passchange = urlencode(passchange) - rsp = wc.grab_json_response_with_status('/api/reset-pass', + rsp = await wc.grab_json_response_with_status('/api/reset-pass', passchange) - rsp = wc.grab_json_response_with_status('/api/session', + rsp = await wc.grab_json_response_with_status('/api/session', method='DELETE') - def config(self, nodename, reset=False): + async def config(self, nodename, reset=False): self.nodename = nodename creds = self.configmanager.get_node_attributes( self.nodename, ['secret.hardwaremanagementuser', @@ -66,6 +65,6 @@ class NodeHandler(bmchandler.NodeHandler): user, passwd, isdefault = self.get_node_credentials( nodename, creds, 'admin', 'admin') if not isdefault: - self.get_webclient(self.DEFAULT_USER, self.DEFAULT_PASS, user, + await self.get_webclient(self.DEFAULT_USER, self.DEFAULT_PASS, user, passwd) - self._bmcconfig(nodename, False) + await self._bmcconfig(nodename, False) diff --git a/confluent_server/confluent/discovery/handlers/megarac.py b/confluent_server/confluent/discovery/handlers/megarac.py index d7d8786a..59e4ec13 100644 --- a/confluent_server/confluent/discovery/handlers/megarac.py +++ b/confluent_server/confluent/discovery/handlers/megarac.py @@ -12,12 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import asyncio + import confluent.discovery.handlers.redfishbmc as redfishbmc -import eventlet.support.greendns - - -getaddrinfo = eventlet.support.greendns.getaddrinfo - class NodeHandler(redfishbmc.NodeHandler): @@ -25,19 +22,19 @@ class NodeHandler(redfishbmc.NodeHandler): return ('admin', 'admin') -def remote_nodecfg(nodename, cfm): +async def remote_nodecfg(nodename, cfm): cfg = cfm.get_node_attributes( nodename, 'hardwaremanagement.manager') ipaddr = cfg.get(nodename, {}).get('hardwaremanagement.manager', {}).get( 'value', None) ipaddr = ipaddr.split('/', 1)[0] - ipaddr = getaddrinfo(ipaddr, 0)[0][-1] + ipaddr = (await asyncio.get_event_loop().getaddrinfo(ipaddr, 0))[0][-1] if not ipaddr: raise Exception('Cannot remote configure a system without known ' 'address') info = {'addresses': [ipaddr]} nh = NodeHandler(info, cfm) - nh.config(nodename) + await nh.config(nodename) if __name__ == '__main__': diff --git a/confluent_server/confluent/discovery/handlers/redfishbmc.py b/confluent_server/confluent/discovery/handlers/redfishbmc.py index 7bc034fe..6d494a15 100644 --- a/confluent_server/confluent/discovery/handlers/redfishbmc.py +++ b/confluent_server/confluent/discovery/handlers/redfishbmc.py @@ -18,11 +18,7 @@ import confluent.exceptions as exc import confluent.netutil as netutil import confluent.util as util import json -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode -import eventlet.green.subprocess as subprocess + from socket import getaddrinfo @@ -68,12 +64,11 @@ class NodeHandler(generic.NodeHandler): self._srvroot = srvroot return self._srvroot - def get_manager_url(self, wc): - #TODO:asyncmerge: make async - mgrs = self.srvroot(wc).get('Managers', {}).get('@odata.id', None) + async def get_manager_url(self, wc): + mgrs = (await self.srvroot(wc)).get('Managers', {}).get('@odata.id', None) if not mgrs: raise Exception("No Managers resource on BMC") - rsp = wc.grab_json_response(mgrs) + rsp = await wc.grab_json_response(mgrs) if len(rsp.get('Members', [])) != 1: raise Exception("Can not handle multiple Managers") mgrurl = rsp['Members'][0]['@odata.id'] @@ -81,7 +76,7 @@ class NodeHandler(generic.NodeHandler): async def mgrinfo(self, wc): if not self._mgrinfo: - self._mgrinfo = await wc.grab_json_response(self.get_manager_url(wc)) + self._mgrinfo = await wc.grab_json_response(await self.get_manager_url(wc)) return self._mgrinfo @@ -331,16 +326,19 @@ class NodeHandler(generic.NodeHandler): raise exc.TargetEndpointUnreachable( 'hardwaremanagement.manager must be set to desired address (No IPv6 Link Local detected)') - def autosign_certificate(self): + async def autosign_certificate(self): nodename = self.nodename hwmgt_method = self.configmanager.get_node_attributes( nodename, 'hardwaremanagement.method').get( nodename, {}).get('hardwaremanagement.method', {}).get('value', 'ipmi') if hwmgt_method != 'redfish': return - subprocess.check_call(['/opt/confluent/bin/nodecertutil', nodename, 'signbmccert', '--days', '47']) + proc = await asyncio.create_subprocess_exec( + '/opt/confluent/bin/nodecertutil', nodename, 'signbmccert', '--days', '47' + ) + await proc.wait() -def remote_nodecfg(nodename, cfm): +async def remote_nodecfg(nodename, cfm): cfg = cfm.get_node_attributes( nodename, 'hardwaremanagement.manager') ipaddr = cfg.get(nodename, {}).get('hardwaremanagement.manager', {}).get( @@ -352,7 +350,7 @@ def remote_nodecfg(nodename, cfm): 'address') info = {'addresses': [ipaddr]} nh = NodeHandler(info, cfm) - nh.config(nodename) + await nh.config(nodename) if __name__ == '__main__': import confluent.config.configmanager as cfm diff --git a/confluent_server/confluent/discovery/handlers/smm.py b/confluent_server/confluent/discovery/handlers/smm.py index d5bd696a..c08207b9 100644 --- a/confluent_server/confluent/discovery/handlers/smm.py +++ b/confluent_server/confluent/discovery/handlers/smm.py @@ -12,11 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +import asyncio import codecs import confluent.discovery.handlers.bmc as bmchandler import confluent.exceptions as exc -import eventlet - import aiohmi.util.webclient as webclient import struct @@ -24,10 +23,8 @@ try: from urllib import urlencode except ImportError: from urllib.parse import urlencode -import eventlet.support.greendns import confluent.netutil as netutil import confluent.util as util -getaddrinfo = eventlet.support.greendns.getaddrinfo from xml.etree.ElementTree import fromstring as rfromstring @@ -93,7 +90,7 @@ class NodeHandler(bmchandler.NodeHandler): wc.request('POST', '/data', apirequest) wc.getresponse().read() - def _webconfignet(self, wc, nodename): + async def _webconfignet(self, wc, nodename): cfg = self.configmanager if 'service:lenovo-smm2' in self.info.get('services', []): # need to enable ipmi for now.. @@ -109,7 +106,7 @@ class NodeHandler(bmchandler.NodeHandler): if smmip: smmip = smmip.split('/', 1)[0] if smmip and ':' not in smmip: - smmip = getaddrinfo(smmip, 0)[0] + smmip = await asyncio.get_event_loop().getaddrinfo(smmip, 0)[0] smmip = smmip[-1][0] if smmip and ':' in smmip: raise exc.NotImplementedException('IPv6 not supported') @@ -219,7 +216,7 @@ class NodeHandler(bmchandler.NodeHandler): wc.set_header('ST2', st2) return wc - def config(self, nodename): + async def config(self, nodename): # SMM for now has to reset to assure configuration applies cd = self.configmanager.get_node_attributes( nodename, ['secret.hardwaremanagementuser', @@ -257,7 +254,7 @@ class NodeHandler(bmchandler.NodeHandler): # Switch to full web based configuration, to mitigate risks with the SMM wc = self._webconfigcreds(username, passwd) self._webconfigrules(wc) - self._webconfignet(wc, nodename) + await self._webconfignet(wc, nodename) # notes for smm: diff --git a/confluent_server/confluent/discovery/handlers/smm3.py b/confluent_server/confluent/discovery/handlers/smm3.py index 784b3051..9ce29ddc 100644 --- a/confluent_server/confluent/discovery/handlers/smm3.py +++ b/confluent_server/confluent/discovery/handlers/smm3.py @@ -12,15 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +import asyncio + import confluent.discovery.handlers.redfishbmc as redfishbmc -import eventlet.support.greendns import confluent.util as util - -getaddrinfo = eventlet.support.greendns.getaddrinfo - - class NodeHandler(redfishbmc.NodeHandler): devname = 'SMM3' maxmacs = 18 # support an enclosure, but try to avoid catching daisy chain @@ -43,19 +40,19 @@ class NodeHandler(redfishbmc.NodeHandler): return ('USERID', 'PASSW0RD') -def remote_nodecfg(nodename, cfm): +async def remote_nodecfg(nodename, cfm): cfg = cfm.get_node_attributes( nodename, 'hardwaremanagement.manager') ipaddr = cfg.get(nodename, {}).get('hardwaremanagement.manager', {}).get( 'value', None) ipaddr = ipaddr.split('/', 1)[0] - ipaddr = getaddrinfo(ipaddr, 0)[0][-1] + ipaddr = await asyncio.get_event_loop().getaddrinfo(ipaddr, 0)[0][-1] if not ipaddr: raise Exception('Cannot remote configure a system without known ' 'address') info = {'addresses': [ipaddr]} nh = NodeHandler(info, cfm) - nh.config(nodename) + await nh.config(nodename) if __name__ == '__main__': @@ -65,5 +62,5 @@ if __name__ == '__main__': info = {'addresses': [[sys.argv[1]]]} print(repr(info)) testr = NodeHandler(info, c) - testr.config(sys.argv[2]) + asyncio.run(testr.config(sys.argv[2])) diff --git a/confluent_server/confluent/discovery/handlers/xcc.py b/confluent_server/confluent/discovery/handlers/xcc.py index 4dc3cb5d..e3b88183 100644 --- a/confluent_server/confluent/discovery/handlers/xcc.py +++ b/confluent_server/confluent/discovery/handlers/xcc.py @@ -462,7 +462,7 @@ class NodeHandler(immhandler.NodeHandler): if status >= 500: if tries < 0: raise Exception('Redfish account management failure') - eventlet.sleep(30) + await asyncio.sleep(30) continue rsp, status = await wc.grab_json_response_with_status( '/redfish/v1/AccountService/Accounts/{0}'.format(uid), diff --git a/confluent_server/confluent/networking/lldp.py b/confluent_server/confluent/networking/lldp.py index 35697dbb..7eb2cac5 100644 --- a/confluent_server/confluent/networking/lldp.py +++ b/confluent_server/confluent/networking/lldp.py @@ -17,7 +17,7 @@ # This provides the implementation of locating MAC addresses on ethernet # switches. It is, essentially, a port of 'MacMap.pm' to confluent. # However, there are enhancements. -# For one, each switch interrogation is handled in an eventlet 'thread' +# For one, each switch interrogation is handled in an async coroutine # For another, MAC addresses are checked in the dictionary on every # switch return, rather than waiting for all switches to check in # (which makes it more responsive when there is a missing or bad switch) @@ -280,7 +280,7 @@ async def _extract_neighbor_data_affluent(switch, user, password, cfm, lldpdata, async def _extract_neighbor_data_b(args): """Build LLDP data about elements connected to switch - args are carried as a tuple, because of eventlet convenience + args are carried as a tuple """ # Safely unpack args with defaults to avoid IndexError switch = args[0] if len(args) > 0 else None