def search_for_instances_in_instancepool(): print("Checking for new instances.....") exo = exoscale.Exoscale(api_key=os.environ.get('EXOSCALE_KEY'), api_secret=os.environ.get('EXOSCALE_SECRET')) zone_at = exo.compute.get_zone(os.environ.get('EXOSCALE_ZONE')) data = [] for instance in exo.compute.list_instances(zone_at): #print(instance.instance_pool) if (instance.instance_pool is not None and instance.instance_pool.id == os.environ.get('EXOSCALE_INSTANCEPOOL_ID')): print("Found instance....") print("{name} {zone} {ip}".format( name=instance.name, zone=instance.zone.name, ip=instance.ipv4_address, )) data.append({ 'targets': [ "{ip}:{port}".format(ip=instance.ipv4_address, port=os.environ.get('TARGET_PORT')) ] }) with open('/srv/service-discovery/config.json', 'w') as outfile: json.dump(data, outfile)
def queryInstances(api_key, api_secret, exoscale_instancepool_id, target_port, exoscale_zone): exo = exoscale.Exoscale(api_key=api_key, api_secret=api_secret) zone = exo.compute.get_zone(name=exoscale_zone) if not zone: pylogger.error("Invalid Zone -- cannot be empty") sys.exit(1) targetList = [] for instance in exo.compute.list_instances(zone): try: instance_pool = instance.instance_pool if instance_pool and exoscale_instancepool_id == instance_pool.id: target = { 'targets': [instance.ipv4_address + ':' + target_port] } pylogger.info("Targets: {0}".format(target)) targetList.append(target) except Exception: pylogger.error("Something went wrong", exc_info=True) pylogger.info("Write targets {0} into {1}".format(targetList, service_config_file)) with open(service_config_file, 'w') as outfile: pylogger.info( "Overwrite the config.json file with content: {0}".format(outfile)) json.dump(targetList, outfile)
def loop_service_discovery(key: str, secret: str, zone_name: str, pool_id: str, port: int, file: str): global finished exo = exoscale.Exoscale(api_key=key, api_secret=secret, config_file="") zone = exo.compute.get_zone(zone_name) failed_sd = 0 while not finished: if failed_sd > 10: raise Exception("Too many service discovery failures.") try: service_discovery(exo, zone, pool_id, port, file) failed_sd = 0 except Exception as err: pprint.pprint(err) failed_sd = failed_sd + 1 time.sleep(5)
def exo(): import exoscale import requests_mock class ExoscaleMock(exoscale.Exoscale): def __init__(self, exo): self.exo = exo self.mocker = requests_mock.Mocker() self.mocker.start() self.boto_stub = Stubber(exo.storage.boto) self.boto_stub.activate() @property def compute(self): return self.exo.compute @property def iam(self): return self.exo.iam @property def dns(self): return self.exo.dns @property def storage(self): return self.exo.storage def mock_post(self, zone, url, resp): self.mocker.post( urljoin("https://api-{}.exoscale.com/v2/".format(zone), url), json=resp, ) def mock_put(self, zone, url, resp): self.mocker.put( urljoin("https://api-{}.exoscale.com/v2/".format(zone), url), json=resp, ) def mock_delete(self, zone, url, resp): self.mocker.delete( urljoin("https://api-{}.exoscale.com/v2/".format(zone), url), json=resp, ) # FIXME: this method shall be renamed into mock_get() once we've finished # transitioning to the Public API V2. def mock_get_v2(self, zone, url, resp): self.mocker.get( urljoin("https://api-{}.exoscale.com/v2/".format(zone), url), json=resp, ) def mock_get(self, url, resp, **kwargs): self.mocker.get(urljoin(self.exo.compute.endpoint, url), json=resp, headers={"Content-Type": "application/json"}, **kwargs) def mock_list(self, list_command, results=[]): resources = { "listAffinityGroups": { "res_key": "listaffinitygroupsresponse", "res_type": "affinitygroup", }, "listApiKeys": { "res_key": "listapikeysreponse", "res_type": "apikey", }, "listDnsDomainRecords": { "res_key": "listdnsdomainrecordsreponse", "res_type": "records", }, "listDnsDomains": { "res_key": "listdnsdomainsreponse", "res_type": "dnsdomain", }, "listNetworks": { "res_key": "listnetworksresponse", "res_type": "network", }, "listNics": { "res_key": "listnicsresponse", "res_type": "nic", }, "listPublicIpAddresses": { "res_key": "listpublicipaddressesresponse", "res_type": "ipaddress", }, "listSecurityGroups": { "res_key": "listsecuritygroupsresponse", "res_type": "securitygroups", }, "listServiceOfferings": { "res_key": "listserviceofferingsresponse", "res_type": "serviceoffering", }, "listSnapshots": { "res_key": "listsnapshotsresponse", "res_type": "snapshot", }, "listSSHKeyPairs": { "res_key": "listsshkeypairsresponse", "res_type": "sshkeypair", }, "listTemplates": { "res_key": "listtemplatesresponse", "res_type": "template", }, "listVirtualMachines": { "res_key": "listvirtualmachinesreponse", "res_type": "virtualmachine", }, "listVolumes": { "res_key": "listvolumesresponse", "res_type": "volume", }, "listZones": { "res_key": "listzonesresponse", "res_type": "zone", }, } if list_command not in resources: raise Exception( "{} command not supported".format(list_command)) self.mock_get( "?command={}".format(list_command), { resources[list_command]["res_key"]: { "count": len(results), resources[list_command]["res_type"]: results, } }, ) def mock_query_async_job_result(self, result=None): self.mock_get( "?command=queryAsyncJobResult", { "queryasyncjobresultresponse": { "jobresult": result if result else { "success": True }, "jobresultcode": 0, "jobstatus": 1, } }, ) def mock_get_operation(self, zone, op_id, ref_id, result=None): self.mocker.get( "https://api-{}.exoscale.com/v2/operation/{}".format( zone, op_id), json=result if result else { "id": op_id, "state": "success", "reference": { "id": ref_id }, }, ) return ExoscaleMock(exoscale.Exoscale(api_key="test", api_secret="test"))
def getInstances(exo, zone, poolId): try: return exo.compute.get_instance_pool(poolId, zone).instances except: return [] exoscale_key = os.getenv('EXOSCALE_KEY') exoscale_secret = os.getenv('EXOSCALE_SECRET') exoscale_zone = os.getenv('EXOSCALE_ZONE') exoscale_instancepool_id = os.getenv('EXOSCALE_INSTANCEPOOL_ID') target_port = os.getenv('TARGET_PORT') exo = exoscale.Exoscale(api_key=exoscale_key, api_secret=exoscale_secret) print("exoscale_zone (should be zone): " + exoscale_zone, flush=True) zone = exo.compute.get_zone(name=exoscale_zone) while True: vms = getInstances(exo, zone, exoscale_instancepool_id) ips = [] for vm in vms: print(vm.ipv4_address, flush=True) ips.append(vm.ipv4_address + ":" + target_port) # need array to get right format jsonObj = [] jsonObj.append({"targets": ips, "labels": {}})
def exo(): import exoscale return exoscale.Exoscale()
return instancePool.instances except: return list() def signalHandler(signum, frame): sys.exit(0) signal.signal(signal.SIGINT, signalHandler) signal.signal(signal.SIGTERM, signalHandler) apiKey = os.getenv('EXOSCALE_KEY') apiSecret = os.getenv('EXOSCALE_SECRET') zone = os.getenv('EXOSCALE_ZONE') poolId = os.getenv('EXOSCALE_INSTANCEPOOL_ID') targetPort = os.getenv('TARGET_PORT') directory = '/srv/service-discovery' filename = 'config.json' pollingInterval = 15 exo = exoscale.Exoscale(api_key=apiKey, api_secret=apiSecret) exoZone = exo.compute.get_zone(zone) while True: runningInstances = getRunningInstances(exo, exoZone, poolId) jsonData = mapRunningInstancesToJSON(runningInstances, targetPort) printJSONObjectToFile(directory, filename, jsonData) time.sleep(pollingInterval)
class SignalHandler: termSignal = False def __init__(self): signal.signal(signal.SIGTERM, self.exitProcess) def exitProcess(self): self.termSignal = True handler = SignalHandler while not handler.termSignal: # Get Exoscale instance exoscaleConnection = exoscale.Exoscale() exoscaleZone = exoscaleConnection.compute.get_zone(zone) instances = list( exoscaleConnection.compute.get_instance_pool(instancePoolId, exoscaleZone).instances) instanceIPv4Addresses = list() for instance in instances: if instance.state == "running": instanceIPv4Addresses.append("\"" + instance.ipv4_address + ":" + str(targetPort) + "\"") # Write file for prometheus targets targetsFile = open("/prometheus/targets.json", "w") targetsFile.write("[{\"targets\": [" + (", ".join(instanceIPv4Addresses)) +
import exoscale from ssh2.session import Session import os import socket exo = exoscale.Exoscale() # connection to an instance via SSH and execute command def exec_ssh_cmd(cmd, host): username = '******' sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, 22)) session = Session() session.handshake(sock) session.agent_auth(username) session = Session() session.userauth_publickey_fromfile(username, '~/.ssh/keys/exoscale') channel = session.open_session() channel.execute(cmd) size, data = channel.read() while size > 0: print(data) size, data = channel.read() channel.close() print("Exit status: %s" % channel.get_exit_status())
import exoscale if __name__ == "__main__": exo = exoscale.Exoscale(api_key="api-key-here", api_secret="api-secret-here", config_file="") zone = exo.compute.get_zone("zone-name-here") ip = exo.compute.get_instance_pool("instance-pool-id-here", zone=zone) ip.scale(ip.size + 1)
import http.server import socketserver import os import signal from http import HTTPStatus import exoscale api_key = os.environ["EXOSCALE_KEY"] api_secret = os.environ["EXOSCALE_SECRET"] api_zone = os.environ["EXOSCALE_ZONE"] instance_pool_id = os.environ["EXOSCALE_INSTANCEPOOL_ID"] listen_port = int(os.environ["LISTEN_PORT"]) exo = exoscale.Exoscale(api_key=api_key, api_secret=api_secret, config_file="") zone = exo.compute.get_zone(api_zone) class WebhookHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): global exo global zone instance_pool = exo.compute.get_instance_pool(instance_pool_id, zone=zone) if self.path == '/up': instance_pool.scale(instance_pool.size + 1) self.send_response(HTTPStatus.OK) elif self.path == '/down': if instance_pool.size > 1: instance_pool.scale(instance_pool.size - 1) self.send_response(HTTPStatus.OK)