def ajax_list_deployments(request): mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) deployments = mc.list_deployments() data = {} data['deployments'] = deployments return render(request, 'marathon_mgmt/ajax_list_deployments.html', data)
def main(args): migration_hosts = args.hosts.replace('"', '').replace('\'', '').split(',') marathon_client = MarathonClient(args.url) # Get the running marathon application dictionary with constraints all_apps = utils.dict_by_key_and_value(lambda x: x.id, lambda y: y.constraints, marathon_client.list_apps()) print(">>> All Running Applications: ") print( json.dumps(all_apps.keys(), sort_keys=True, indent=4, separators=(',', ': '))) # Constraints to remove sentinels = map(lambda x: MarathonConstraint('hostname', 'UNLIKE', x), migration_hosts) # Find all apps with a leftover constraint filtered_apps = {} for sentinel in sentinels: for app_id in all_apps: if sentinel in all_apps[app_id]: to_update = {app_id: all_apps[app_id]} print ">>> Adding app to filtered list: %s" % (app_id) filtered_apps.update(to_update) # Tasks unmigration unmigrate_tasks(marathon_client, filtered_apps, sentinels, args.force)
def test_list_tasks_with_app_id(m): fake_response = '{ "tasks": [ { "appId": "/anapp", "healthCheckResults": [ { "alive": true, "consecutiveFailures": 0, "firstSuccess": "2014-10-03T22:57:02.246Z", "lastFailure": null, "lastSuccess": "2014-10-03T22:57:41.643Z", "taskId": "bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799" } ], "host": "10.141.141.10", "id": "bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799", "ports": [ 31000 ], "servicePorts": [ 9000 ], "stagedAt": "2014-10-03T22:16:27.811Z", "startedAt": "2014-10-03T22:57:41.587Z", "version": "2014-10-03T22:16:23.634Z" }, { "appId": "/anotherapp", "healthCheckResults": [ { "alive": true, "consecutiveFailures": 0, "firstSuccess": "2014-10-03T22:57:02.246Z", "lastFailure": null, "lastSuccess": "2014-10-03T22:57:41.649Z", "taskId": "bridged-webapp.ef0b5d91-4b4a-11e4-ae49-56847afe9799" } ], "host": "10.141.141.10", "id": "bridged-webapp.ef0b5d91-4b4a-11e4-ae49-56847afe9799", "ports": [ 31001 ], "servicePorts": [ 9000 ], "stagedAt": "2014-10-03T22:16:33.814Z", "startedAt": "2014-10-03T22:57:41.593Z", "version": "2014-10-03T22:16:23.634Z" } ] }' m.get('http://fake_server/v2/tasks', text=fake_response) mock_client = MarathonClient(servers='http://fake_server') actual_deployments = mock_client.list_tasks(app_id='/anapp') expected_deployments = [ models.task.MarathonTask( app_id="/anapp", health_check_results=[ models.task.MarathonHealthCheckResult( alive=True, consecutive_failures=0, first_success="2014-10-03T22:57:02.246Z", last_failure=None, last_success="2014-10-03T22:57:41.643Z", task_id= "bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799") ], host="10.141.141.10", id="bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799", ports=[31000], service_ports=[9000], staged_at="2014-10-03T22:16:27.811Z", started_at="2014-10-03T22:57:41.587Z", version="2014-10-03T22:16:23.634Z") ] assert actual_deployments == expected_deployments
def test_list_tasks_without_app_id(m): fake_response = '{ "tasks": [ { "appId": "/anapp", "healthCheckResults": ' \ '[ { "alive": true, "consecutiveFailures": 0, "firstSuccess": "2014-10-03T22:57:02.246Z", "lastFailure": null, ' \ '"lastSuccess": "2014-10-03T22:57:41.643Z", "taskId": "bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799" } ],' \ ' "host": "10.141.141.10", "id": "bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799", "ports": [ 31000 ], ' \ '"servicePorts": [ 9000 ], "stagedAt": "2014-10-03T22:16:27.811Z", "startedAt": "2014-10-03T22:57:41.587Z", ' \ '"version": "2014-10-03T22:16:23.634Z" }, { "appId": "/anotherapp", ' \ '"healthCheckResults": [ { "alive": true, "consecutiveFailures": 0, "firstSuccess": "2014-10-03T22:57:02.246Z", ' \ '"lastFailure": null, "lastSuccess": "2014-10-03T22:57:41.649Z", "taskId": "bridged-webapp.ef0b5d91-4b4a-11e4-ae49-56847afe9799" } ], ' \ '"host": "10.141.141.10", "id": "bridged-webapp.ef0b5d91-4b4a-11e4-ae49-56847afe9799", "ports": [ 31001 ], "servicePorts": [ 9000 ], ' \ '"stagedAt": "2014-10-03T22:16:33.814Z", "startedAt": "2014-10-03T22:57:41.593Z", "version": "2014-10-03T22:16:23.634Z" } ] }' m.get('http://fake_server/v2/tasks', text=fake_response) mock_client = MarathonClient(servers='http://fake_server') actual_deployments = mock_client.list_tasks() expected_deployments = [ models.task.MarathonTask( app_id="/anapp", health_check_results=[ models.task.MarathonHealthCheckResult( alive=True, consecutive_failures=0, first_success="2014-10-03T22:57:02.246Z", last_failure=None, last_success="2014-10-03T22:57:41.643Z", task_id="bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799" ) ], host="10.141.141.10", id="bridged-webapp.eb76c51f-4b4a-11e4-ae49-56847afe9799", ports=[ 31000 ], service_ports=[ 9000 ], staged_at="2014-10-03T22:16:27.811Z", started_at="2014-10-03T22:57:41.587Z", version="2014-10-03T22:16:23.634Z" ), models.task.MarathonTask( app_id="/anotherapp", health_check_results=[ models.task.MarathonHealthCheckResult( alive=True, consecutive_failures=0, first_success="2014-10-03T22:57:02.246Z", last_failure=None, last_success="2014-10-03T22:57:41.649Z", task_id="bridged-webapp.ef0b5d91-4b4a-11e4-ae49-56847afe9799" ) ], host="10.141.141.10", id="bridged-webapp.ef0b5d91-4b4a-11e4-ae49-56847afe9799", ports=[31001], service_ports=[9000], staged_at="2014-10-03T22:16:33.814Z", started_at="2014-10-03T22:57:41.593Z", version="2014-10-03T22:16:23.634Z" )] assert actual_deployments == expected_deployments
def clean_deploy_ids(self): marathon_client = MarathonClient('http://' + str(marathon_host) + ':' + str(marathon_port)) apps = marathon_client.list_apps() app_ids = [x.id for x in apps] for deploy_id in self.deploy_ids: if not deploy_id in app_ids: print 'deploy_id is not in app id! '+str(deploy_id)
def _update_application(client: MarathonClient, app: MarathonApp, definition_path: str, do_backup: bool = False) -> Union[str, bool]: if do_backup: if not os.path.isdir('./backups'): os.mkdir('./backups/') print('Created backups directory') backup = client.get_app(app.id).to_json() backup_path = './backups/{}_{}.json'.format( mangling.appid_to_filename(app.id), time.strftime("%Y-%m-%d_%H:%M:%S")) with open(backup_path, 'w') as backup_file: backup_file.write(backup) print('\nBacked app into: {}'.format(backup_path)) else: backup_path = '' print('Updating app: {} (from: {})'.format(app.id, definition_path)) deployment = client.update_app(app.id, app, force=True) # TODO: Handle failure # Return the deployed backup file to build rollback order, if necessary # or False if a user-initiated rollback completed successfully if not wait_for_deployment(client, deployment): client.restart_app(app.id) return False if not wait_for_deployment(client, deployment) else backup_path
def new_app(request): data = {} if request.method == "POST": data["msg"] = "Post" post_params = {} for key in request.POST: if key.startswith("filehidden"): fkey = key[11:] if request.FILES.get(fkey, None): post_file = request.FILES[fkey] file_content = "" for chunk in post_file.chunks(): file_content += chunk.decode("utf8") post_params[fkey] = convert(file_content) else: post_params[fkey] = request.POST[key] else: post_params[key] = request.POST[key] template = Template.objects.get(pk=post_params["template_id"]) content = template.content % post_params data["content"] = content mc = MarathonClient("http://{}:{}".format(settings.MARATHON["host"], settings.MARATHON["port"])) try: mc.create_app_by_json(content) data["result"] = "Success" except Exception as e: data["result"] = str(e) templates = Template.objects.filter(type="marathon").all() for template in templates: template.params = template.param_set.order_by("id") data["templates"] = templates return render(request, "marathon_mgmt/new_app.html", data)
def enable_logstash(): print "Checking ELK entries\n" endpoint = os.getenv('MARATHON_ENDPOINT') username = os.getenv('MARATHON_HTTP_USER') password = os.getenv('MARATHON_HTTP_PASSWORD') elk_host = None if endpoint: try: print 'Discovering configuration from %s\n' % endpoint c = MarathonClient('https://%s' % endpoint, username=username, password=password) tasks = c.list_tasks('yroblaelk') for task in tasks: if task.started_at: elk_host = task.host break except: pass # check entries in wsrep_cluster_address if elk_host: print 'Found ELK address %s\n' % elk_host for line in fileinput.input(LOGSTASH_CONF_FILE, inplace=True): line_content = line sys.stdout.write(line.replace("ELK_HOST", elk_host)) # reboot logstash subprocess.call(["service", "logstash-forwarder", "restart"])
def __init__(self, target, auth, options, pkey): super(MarathonHTTPClient, self).__init__(target, auth, options, pkey) self.target = settings.MARATHON_HOST self.registry = settings.REGISTRY_HOST + ':' + settings.REGISTRY_PORT self.client = MarathonClient('http://' + self.target + ':8180') self.fleet = FleetHTTPClient('/var/run/fleet.sock', auth, options, pkey)
def update(service, instances = 1): # # set up marathon client and launch container # print 'updating ' + service image_string = 'docker:///' + data['services'][service]['image'] print image_string marathon_client = MarathonClient('http://' + str(data['marathon']['host']) + ':' + str(data['marathon']['port'])) app = marathon_client.get_app(service) # # set up options for cassandra # options = [] if service == "cassandra": options = ["-p", "7000:7000", "-p", "9042:9042", "-p", "9160:9160", "-p", "22000:22", "-p", "5000:5000"] # ports = [] # constraints = [["hostname", "UNIQUE"]] marathon_client.update_app( service, app, instances = instances, container = { "image" : image_string, "options" : options } )
def update_app(app_id, config, instances = 1): # # set up marathon client and launch container # image_string = 'docker:///' + config['image'] marathon_client = MarathonClient('http://' + str(marathon_host) + ':' + str(marathon_port)) app = marathon_client.get_app(app_id) # # set up options for cassandra TODO this is terrible dawg # decoded = namespacer.decode_marathon_id(app_id) options = [] if str(decoded['service']) == "cassandra": options = ["-p", "7000:7000", "-p", "9042:9042", "-p", "9160:9160", "-p", "22000:22", "-p", "5000:5000"] # ports = [] # constraints = [["hostname", "UNIQUE"]] marathon_client.update_app( app_id, app, instances = instances, container = { "image" : image_string, "options" : options } )
def sync_marathon_app(): """Identify the hosts and ports of executing tasks Optional environment variables: MARATHON_ROOT_URL: protocol, address or ip and port to Marathon MARATHON_APP: app name within Marathon used to group all tasks (server instances) MARATHON_APP_PORT: internal port of service (internal to docker container: default of 8080) :return: """ # Identify the hosts and ports of executing tasks try: c = None if len(DCOS_OAUTH_TOKEN): c = MarathonClient(MARATHON_ROOT_URLS, auth_token=DCOS_OAUTH_TOKEN) else: c = MarathonClient(MARATHON_ROOT_URLS) app = c.get_app(MARATHON_APP) port_index = find_port_index_by_container_port(app, MARATHON_APP_PORT) if port_index is None: raise Exception('Unable to correlate container to host port.') instances = [] for task in app.tasks: logging.info('Queuing configuration refresh of %s at %s:%s' % (task.id, task.host, task.ports[port_index])) instances.append('%s:%s' % (task.host, task.ports[port_index])) reload_config(instances) except MarathonError, ex: print 'Error making Marathon API call: %s' % ex.message
class MarathonDeployer(object): def __init__(self, marathon_url): self.url = marathon_url self.client = MarathonClient(self.url) def deploy(self, task_chain, environment_name): deployed_chain = DeployedTaskChain(task_chain, environment_name) for task in deployed_chain.list_all_tasks(): task_id = task['id'] safe_name = task_id.lower() # safe_name = task['name'].replace('.', '').lower() try: if self.client.get_app(safe_name): self.client.delete_app(safe_name) time.sleep(2) except Exception: pass app = MarathonApp(cmd='/var/riversnake/invoke.py {0} {1} {2}'.format( task_chain.flow_name, environment_name, task_id), mem=16, cpus=1) self.client.create_app(safe_name, app)
def servermarathon(): APP = os.environ['APPNAME'] # STRING = os.environ['STRING'] # content = STRING # contentlist = content.split('&') # list = [] # for i in contentlist: # p = i.split('=') # p = p[1] # l = list.append(p) # (maurl,mau,map) =tuple(list) # marathonip = maurl # user = mau # password = map c = MarathonClient(marathonip,username=user,password=password) buildFile=open('build.txt','r') dockerimage = buildFile.readline() buildFile.close() readed = json.load(open('temp.json', 'r')) readed['container']['docker']['image'] = dockerimage readed['id'] = APP json.dump(readed, open('app.json', 'w')) try: c.delete_app(APP,force=True) print 'delete' except : pass sleep(3) u= user+':'+password cmd1 = os.system ('curl -u %s -X POST -H "Content-Type: application/json" %s/v2/apps [email protected]' %(u,marathonip))
def is_deployed(self): marathon_client = MarathonClient('http://' + str(marathon_host) + ':' + str(marathon_port)) apps = marathon_client.list_apps() my_encoded_id = self.encode_marathon_id for app in apps: if my_encoded_id in app.id: return True return False
def update_app_tag(client: MarathonClient, appid: str, new_tag: str): app = client.get_app(appid) reg, img = mangling.split_image_name(app.container.docker.image) img, _ = mangling.split_image_tag(img) new_image = mangling.rebuild_image_name(reg, img, new_tag) app.container.docker.image = new_image deployment = client.update_app(appid, app, force=True) wait_for_deployment(client, deployment)
def in_place_restart(client: MarathonClient, appid: str): pre = client.get_app(appid).instances deployment = client.scale_app(appid, 0) wait_for_deployment(client, deployment) print('Scaled {} down to 0'.format(appid)) deployment = client.scale_app(appid, pre) wait_for_deployment(client, deployment) print('{} back at {} again'.format(appid, pre))
def launch_qsf(marathon_url): logging.info('Launching QSF using %s' %(marathon_url)) # launch via Marathon REST API c = MarathonClient(marathon_url) c.create_app('dromedar-qsf', MarathonApp(cmd='python dromedar-master/qsf.py %s' %(marathon_url), uris=['https://github.com/mhausenblas/dromedar/archive/master.zip'], mem=100, cpus=.5)) logging.info('QSF up and running.')
def _get_hosts_with_container(self, context, cluster): marathon_client = MarathonClient( 'http://' + cluster.api_address + '/marathon/') hosts = set() for task in marathon_client.list_tasks(): hosts.add(task.host) return hosts
def get_marathon_app_id(self): marathon_client = MarathonClient('http://' + str(marathon_host) + ':' + str(marathon_port)) apps = marathon_client.list_apps() my_encoded_id = self.encode_marathon_id for app in apps: if app.id == my_encoded_id: return app.id return None
def list_app(request): mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) apps = mc.list_apps() apps = sorted(apps, key=lambda app: app.id) for app in apps: app.tag_id = app.id.replace("/","__") data = {'apps': apps} return render(request, 'marathon_mgmt/list_app.html', data)
class MarathonCluster(object): def __init__(self, scheduler, executable='dask-worker', docker_image='mrocklin/dask-distributed:1.15.2', marathon_address='http://localhost:8080', name=None, **kwargs): self.scheduler = scheduler self.executor = ThreadPoolExecutor(1) # Create Marathon App to run dask-worker args = [executable, scheduler.address, '--name', '$MESOS_TASK_ID', # use Mesos task ID as worker name '--worker-port', '$PORT_WORKER', '--bokeh-port', '$PORT_BOKEH', '--nanny-port', '$PORT_NANNY', '--http-port', '$PORT_HTTP'] ports = [{'port': 0, 'protocol': 'tcp', 'name': name} for name in ['worker', 'nanny', 'http', 'bokeh']] if 'mem' in kwargs: args.extend(['--memory-limit', str(int(kwargs['mem'] * 0.6 * 1e6))]) kwargs['cmd'] = ' '.join(args) container = MarathonContainer({'image': docker_image}) app = MarathonApp(instances=0, container=container, port_definitions=ports, **kwargs) # Connect and register app self.client = MarathonClient(marathon_address) self.app = self.client.create_app(name or 'dask-%s' % uuid.uuid4(), app) def scale_up(self, instances): self.executor.submit(self.client.scale_app, self.app.id, instances=instances) def scale_down(self, workers): for w in workers: self.executor.submit(self.client.kill_task, self.app.id, self.scheduler.worker_info[w]['name'], scale=True) def __enter__(self): return self def __exit__(self, *args): self.close() def close(self): self.client.delete_app(self.app.id, force=True)
def num_started_tasks(app_id): count = 0 marathon_client = MarathonClient('http://' + str(marathon_host) + ':' + str(marathon_port)) app = marathon_client.get_app(app_id) tasks = app.tasks for task in tasks: if task.started_at: count += 1 return count
def get_hosts_dict(self): hosts = {} for app in MarathonClient.list_apps(self): for task in MarathonClient.get_app(self, app.id).tasks: host = task.host if not host in hosts: hosts[host] = [] hosts[host].append(task) return hosts
def get_hosts_dict(self): hosts={} for app in MarathonClient.list_apps(self): for task in MarathonClient.get_app(self,app.id).tasks: host = task.host if not host in hosts: hosts[host]=[] hosts[host].append(task) return hosts
def list_app(request): mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) apps = mc.list_apps() apps = sorted(apps, key=lambda app: app.id) for app in apps: app.tag_id = app.id.replace("/", "__") data = {'apps': apps} return render(request, 'marathon_mgmt/list_app.html', data)
def get_deployed_labeled_group_ids(self, labels): ids = [] marathon_client = MarathonClient('http://' + str(marathon_host) + ':' + str(marathon_port)) apps = marathon_client.list_apps() for app in apps: decoded = decode_marathon_id(app.id) if labels == decoded['labels'] and self.name == decoded['service']: # return app.id ids.append(app.id) return ids
def ajax_deployments(request): mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) deployments = mc.list_deployments() data = {} for deployment in deployments: deployment.complete = (deployment.current_step-1) * 100 / deployment.total_steps data['deployments'] = deployments data['total_depl'] = len(deployments) return render(request, 'marathon_mgmt/ajax_deployments.html', data)
def dashboard(request): data = {} data['total_template'] = Template.objects.count() mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) data['total_app'] = len(mc.list_apps()) cclient = chronos.connect('{}:{}'.format(settings.CHRONOS['host'], settings.CHRONOS['port'])) jobs = cclient.list() data['total_job'] = len(cclient.list()) data['total_watcher'] = len(settings.WATCHER_THREADS) return render(request, 'dashboard/dashboard.html',data)
def create_client(urls: str): marathonlist = urls.split(',') client = MarathonClient(marathonlist) try: if client.ping().strip() != b'pong': raise MarathonError except MarathonError: print('Could not connect to Marathon in {}'.format(marathonlist)) sys.exit(1) return client
def __init__(self, scheduler, marathon, name=None, nprocs=1, nthreads=0, docker='daskos/daskathon', volumes=[], **kwargs): self.scheduler = scheduler self.executor = ThreadPoolExecutor(1) self.client = MarathonClient(marathon) self.name = name or 'dask-%s' % uuid.uuid4() self.docker = docker self.volumes = volumes self.nprocs = nprocs self.nthreads = nthreads self.options = kwargs
def undeploy(app_name): """Calls marathon API to undeploy application :param app_name: :return: """ marathon_addresses = _addresses() cli = MarathonClient(marathon_addresses) if _is_deployed(cli, app_name): return cli.delete_app(app_name) else: return None
def ajax_deployments(request): mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) deployments = mc.list_deployments() data = {} for deployment in deployments: deployment.complete = (deployment.current_step - 1) * 100 / deployment.total_steps data['deployments'] = deployments data['total_depl'] = len(deployments) return render(request, 'marathon_mgmt/ajax_deployments.html', data)
def __init__(self, scheduler, executable='dask-worker', docker_image='mrocklin/dask-distributed', marathon_address='http://localhost:8080', username=None, password=None, auth_token=None, app_name=None, **kwargs): self.scheduler = scheduler self.executor = ThreadPoolExecutor(1) # Create Marathon App to run dask-worker args = [ executable, scheduler.address, '--name', '$MESOS_TASK_ID', # use Mesos task ID as worker name '--worker-port', '$PORT_WORKER', '--nanny-port', '$PORT_NANNY', '--http-port', '$PORT_HTTP' ] ports = [{ 'port': 0, 'protocol': 'tcp', 'name': port_name } for port_name in ['worker', 'nanny', 'http']] if 'mem' in kwargs: args.extend( ['--memory-limit', str(int(kwargs['mem'] * 0.6 * 1e6))]) kwargs['cmd'] = ' '.join(args) container = MarathonContainer({'image': docker_image}) app = MarathonApp(instances=0, container=container, port_definitions=ports, **kwargs) # Connect and register app self.client = MarathonClient(servers=marathon_address, username=username, password=password, auth_token=auth_token) self.app = self.client.create_app(app_name or 'dask-%s' % uuid.uuid4(), app)
def dcos_login(): # Defaults servers for both DCOS 1.10+ CE and EE. servers = os.getenv('MARATHON_SERVERS', 'http://marathon.mesos:8080,https://marathon.mesos:8443').split(',') if SERVICE_SECRET: print('Attempting token auth to Marathon...') client = MarathonClient(servers, auth_token=DCOSServiceAuth(json.loads(SERVICE_SECRET)).token, verify=False) else: print('Attempting unauthenticated access to Marathon...') client = MarathonClient(servers, verify=False) return client
def launch_drillbits(marathon_url, scale_factor): logging.info('Launching Drillbits using %s and scale factor %d' %(marathon_url, int(scale_factor))) # launch Drillbits via Marathon REST API c = MarathonClient(marathon_url) # c.create_app('dromedar-drill', MarathonApp(cmd='dromedar-master/launch-drillbit.sh', uris=['https://github.com/mhausenblas/dromedar/archive/master.zip'], mem=400, cpus=1)) c.create_app('dromedar-drill', MarathonApp(cmd='sudo /opt/drill/apache-drill-0.8.0/bin/drillbit.sh start', mem=400, cpus=1)) print('Drillbits are deployed: DATASETSIZE, NUM_DRILLBITS') httpd = SocketServer.TCPServer(("", QSF_PORT), SimpleHTTPServer.SimpleHTTPRequestHandler) logging.info('Now listening to change requests on port %d' %(QSF_PORT)) httpd.serve_forever()
def get_random_marathon_task(app_id): """Connect to Marathon and return a random task for a given application ID. :param app_id: The Marathon application ID. :return: tuple of the instance IP or hostname and listening port. """ c = MarathonClient('http://{}'.format(options.marathon_host)) app = c.get_app(app_id) task_host, task_port = None, None rand = randrange(0, len(app.tasks)) task_host = app.tasks[rand].host task_port = app.tasks[rand].ports[0] return task_host, task_port
def get_random_marathon_task(app_id): """Connect to Marathon and return a random task for a given application ID. :param app_id: The Marathon application ID. :return: tuple of the instance IP or hostname and listening port. """ c = MarathonClient("http://{}".format(options.marathon_host)) app = c.get_app(app_id) task_host, task_port = None, None rand = randrange(0, len(app.tasks)) task_host = app.tasks[rand].host task_port = app.tasks[rand].ports[0] return task_host, task_port
def launch(service): print 'launching ' + service service_dict = data['services'][service] image = service_dict['image'] try: ports = service_dict['ports'].values() except: ports = [] instances = 1 if not service_dict.get('instances') else service_dict.get('instances') cpus = 0.3 if not service_dict.get('cpus') else service_dict.get('cpus') mem = 512 if not service_dict.get('mem') else service_dict.get('mem') # # env variables # env = {} env['ETCD_HOST_ADDRESS'] = data['etcd']['host'] env['SERVICE_NAME'] = service # set up custom environment variables custom_env = service_dict.get('environment') if custom_env: for key in custom_env.keys(): env[key] = custom_env[key] options = [] constraints = [] # # TODO add support for this # if service == "cassandra": options = ["-p", "7000:7000", "-p", "9042:9042", "-p", "9160:9160", "-p", "22000:22", "-p", "5000:5000"] ports = [] constraints = [["hostname", "UNIQUE"]] # # set up marathon client and launch container # marathon_client = MarathonClient('http://' + str(data['marathon']['host']) + ':' + str(data['marathon']['port'])) marathon_client.create_app( container = { "image" : str("docker:///"+image), "options" : options }, id = service, instances = str(instances), constraints = constraints, cpus = str(cpus), mem = str(mem), env = env, ports = ports #should be listed in order they appear in dockerfile )
def test_get_deployments(m): fake_response = '[ { "affectedApps": [ "/test" ], "id": "fakeid", "steps": [ [ { "action": "ScaleApplication", "app": "/test" } ] ], "currentActions": [ { "action": "ScaleApplication", "app": "/test" } ], "version": "fakeversion", "currentStep": 1, "totalSteps": 1 } ]' m.get('http://fake_server/v2/deployments', text=fake_response) mock_client = MarathonClient(servers='http://fake_server') actual_deployments = mock_client.list_deployments() expected_deployments = [ models.MarathonDeployment( id=u"fakeid", steps=[[models.MarathonDeploymentAction(action="ScaleApplication", app="/test")]], current_actions=[models.MarathonDeploymentAction(action="ScaleApplication", app="/test")], current_step=1, total_steps=1, affected_apps=[u"/test"], version=u"fakeversion" )] assert expected_deployments == actual_deployments
def ajax_list_apps(request): mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) apps = mc.list_apps() apps = sorted(apps, key=lambda app: app.id) filter_name = request.GET.get('filter_name', "") if filter_name != "": for app in apps[:]: app.tag_id = app.id.replace("/","__") if app.id.find(filter_name) == -1: apps.remove(app) else: for app in apps: app.tag_id = app.id.replace("/","__") data = {'apps': apps} return render(request, 'marathon_mgmt/ajax_list_apps.html', data)
def main(): logging.basicConfig(stream=sys.stderr, level=getattr(logging, 'INFO')) logging.getLogger("requests.packages.urllib3.connectionpool").setLevel( "ERROR") logging.getLogger("marathon").setLevel("ERROR") logger = logging.getLogger("autoscaling") engine = create_engine("mysql://{}:{}@{}:{}/{}".format( MYSQLDB["USERNAME"], MYSQLDB["PASSWORD"], MYSQLDB["HOST"], MYSQLDB["PORT"], MYSQLDB["DBNAME"]), encoding='utf-8', echo=False) Session = sessionmaker(bind=engine) mysql_client = Session() marathon_client = MarathonClient('http://' + MARATHON['HOST'] + ':' + MARATHON['PORT']) influxdb_client = InfluxDBClient(INFLUXDB["HOST"], INFLUXDB["PORT"], INFLUXDB["USERNAME"], INFLUXDB["PASSWORD"], INFLUXDB["DBNAME"]) app_uuid = sys.argv[1] app = mysql_client.query(WebApp).filter_by(uuid=app_uuid).first() if app: decider = BaseRuleDecider(app, influxdb_client, marathon_client) logger.info("Start autoscaling: " + app_uuid) autoscaling = AutoScaling(decider, TIME_INTERVAL) autoscaling.run() else: logger.error("App uuid not found: " + app_uuid)
def create_client(urls: str, user: str, password: str, https_verify: bool): marathonlist = urls.split(',') client = MarathonClient(marathonlist, username=user, password=password, verify=https_verify, timeout=10) # in seconds try: ping_answer = client.ping().strip().decode() print(ping_answer) if ping_answer != '"pong"': raise MarathonError except MarathonError: print('Could not connect to Marathon in {}'.format(marathonlist)) sys.exit(1) return client
def re_deploy(app_name, app_file): """Calls marathon API to redeploy application with new file as request body :param app_name: :param app_file: :return: """ with open(app_file, 'r') as content_file: content = content_file.read() app_attr = json.loads(content) marathon_addresses = _addresses() cli = MarathonClient(marathon_addresses) if _is_deployed(cli, app_name): return cli.update_app(app_name, models.MarathonApp.from_json(app_attr)) else: return None
def marathon_api_launch(image, options, marathon_app_id, instances, constraints, cpus, mem, env, ports): marathon_client = MarathonClient('http://' + str(marathon_host) + ':' + str(marathon_port)) marathon_client.create_app( container = { "image" : str("docker:///"+image), "options" : options }, id = marathon_app_id, instances = str(instances), constraints = constraints, cpus = str(cpus), mem = str(mem), env = env, ports = ports #should be listed in order they appear in dockerfile ) return marathon_app_id
def __init__(self, app_name, config): self.logger = logging.getLogger("autoscaling") self.logger.setLevel(logging.DEBUG) self.logger.debug("Init object scaler...") self.config = config self.logger.debug("Connect RESTful mariadb and get policies...") conn = http.client.HTTPConnection(config["MARIA_RESTFUL"]['host'], config["MARIA_RESTFUL"]['port']) conn.request("GET", "/app/name/"+app_name) json_app = conn.getresponse().read().decode("utf-8") self.app = json.loads(json_app) conn.request("GET", "/app/name/"+app_name+"/policies") json_policies = conn.getresponse().read().decode("utf-8") self.app["policies"] = json.loads(json_policies) self.logger.debug("Connect influxdb and marathon...") self.influx_client = InfluxDBClient(config["INFLUXDB"]["host"], config["INFLUXDB"]["port"], config["INFLUXDB"]["username"], config["INFLUXDB"]["password"], config["INFLUXDB"]["db_name"]) self.marathon_client = MarathonClient('http://'+config["MARATHON"]['host']+':'+config["MARATHON"]['port']) self.app["instance"] = self.marathon_client.get_app(app_name).instances self.app["mem"] = self.marathon_client.get_app(app_name).mem self.app["cpus"] = self.marathon_client.get_app(app_name).cpus self.logger.debug("Reconfig haproxy.cfg...") os.system("sudo ./servicerouter.py --marathon http://"+config["MARATHON"]["host"]+":"+config["MARATHON"]["port"]+" --haproxy-config /etc/haproxy/haproxy.cfg")
def ajax_list_apps(request): mc = MarathonClient('http://{}:{}'.format(settings.MARATHON['host'], settings.MARATHON['port'])) apps = mc.list_apps() apps = sorted(apps, key=lambda app: app.id) filter_name = request.GET.get('filter_name', "") if filter_name != "": for app in apps[:]: app.tag_id = app.id.replace("/", "__") if app.id.find(filter_name) == -1: apps.remove(app) else: for app in apps: app.tag_id = app.id.replace("/", "__") data = {'apps': apps} return render(request, 'marathon_mgmt/ajax_list_apps.html', data)
def test_get_deployments_pre_1_0(): fake_response = """[ { "affectedApps": [ "/test" ], "id": "fakeid", "steps": [ [ { "action": "ScaleApplication", "app": "/test" } ] ], "currentActions": [ { "action": "ScaleApplication", "app": "/test" } ], "version": "fakeversion", "currentStep": 1, "totalSteps": 1 } ]""" with requests_mock.mock() as m: m.get('http://fake_server/v2/deployments', text=fake_response) mock_client = MarathonClient(servers='http://fake_server') actual_deployments = mock_client.list_deployments() expected_deployments = [ models.MarathonDeployment( id=u"fakeid", steps=[[ models.MarathonDeploymentAction(action="ScaleApplication", app="/test") ]], current_actions=[ models.MarathonDeploymentAction(action="ScaleApplication", app="/test") ], current_step=1, total_steps=1, affected_apps=[u"/test"], version=u"fakeversion") ] assert expected_deployments == actual_deployments
def start(self): marathon_client = MarathonClient(self.config) apps = marathon_client.get_marathon_apps() running_apps = [] running_task = {} for app in apps: app_id = self.format_app_id(app["id"]) running_apps.append(app_id) running_task[app_id] = self.__get_app_tasks(app_id) print("start to update grafana templates") self.update_templates(running_task) self.pre_task = running_task print("finish updating") print("delete useless templates") self.delete_app_templates(running_apps) self.pre_apps = running_apps print("finish deleting useless templates")
def __init__(self, target, auth, options, pkey): self.target = settings.MARATHON_HOST self.auth = auth self.options = options self.pkey = pkey self.registry = settings.REGISTRY_HOST + ':' + settings.REGISTRY_PORT self.client = MarathonClient('http://'+self.target+':8180') self.fleet = FleetHTTPClient('/var/run/fleet.sock', auth, options, pkey)
def get_marathon_client(): try: MARATHON_HOST = get_setting("marathon_host", "10.10.10.51") MARATHON_PORT = int(get_setting("marathon_port", 8080)) marathon_client = MarathonClient('http://{}:{}'.format( MARATHON_HOST, MARATHON_PORT)) return marathon_client except Exception as e: raise Exception("unconnect to marathon")
def dcos_login(): # Defaults servers for both DCOS 1.7 and 1.8. 1.8 added HTTPS within DCOS EE clusters. servers = os.getenv('MARATHON_SERVERS', 'http://marathon.mesos:8080,https://marathon.mesos:8443').split(',') oauth_token = os.getenv('DCOS_OAUTH_TOKEN', '').strip() username = os.getenv('DCOS_USER', '').strip() password = os.getenv('DCOS_PASS', '').strip() if len(oauth_token): print('Attempting token auth to Marathon...') client = MarathonClient(servers, auth_token=oauth_token) elif len(username) and len(password): print('Attempting basic auth to Marathon...') client = MarathonClient(servers, username=username, password=password) else: print('Attempting unauthenticated access to Marathon...') client = MarathonClient(servers) return client
def new_deploy(app_name, app_file): """Calls marathon API to make new deployment of application given file as request body :param app_name: :param app_file: :return: """ marathon_addresses = _addresses() with open(app_file, 'r') as content_file: content = content_file.read() app_attr = json.loads(content) cli = MarathonClient(marathon_addresses) if not _is_deployed(cli, app_name): m_app = models.MarathonApp.from_json(app_attr) created_app = cli.create_app(app_name, m_app) return created_app.to_json() else: return None
def get_marathon_client(url, user, passwd): """Get a new marathon client connection in the form of a MarathonClient object. :param url: The url to connect to marathon at :param user: The username to connect with :param passwd: The password to connect with :returns: A new marathon.MarathonClient object""" log.info("Connecting to Marathon server at: %s", url) return MarathonClient(url, user, passwd, timeout=30)
def main(args): migration_hosts = args.hosts.replace('"','').replace('\'','').split(',') marathon_client = MarathonClient(args.url) # Get the running marathon application dictionary running_instances = utils.dict_by_key_and_value(lambda x: x.id, lambda y: y.instances, marathon_client.list_apps()) print(">>> Total Running Applications: ") print(json.dumps(running_instances, sort_keys=True, indent=4, separators=(',', ': '))) # Get the running marathon applications for all hosts which are going for maintenance all_tasks = marathon_client.list_tasks() filtered_tasks = [task for task in all_tasks if task.host in migration_hosts] dicted_tasks = utils.dict_by_key(lambda x: x.app_id, filtered_tasks) print(">>> Total Running Application: ") print(json.dumps(dicted_tasks.keys(), sort_keys=True, indent=4, separators=(',', ': '))) # Tasks migration migrate_tasks(marathon_client, dicted_tasks, migration_hosts, args.force)