def initiate_swarm(): client.swarm.init() print('Swarm initiated...') benchmark = client.services.create( 'nclcloudcomputing/javabenchmarkapp:latest', endpoint_spec=EndpointSpec(mode='vip', ports={4000: 8080}), mode=ServiceMode(mode='replicated', replicas=2), name='benchmarkapp', ) print('Benchmark service initialized with id ' + benchmark.id) visualizer = client.services.create( 'dockersamples/visualizer', endpoint_spec=EndpointSpec(mode='vip', ports={5000: 8080}), mounts=['/var/run/docker.sock:/var/run/docker.sock'], name='visualizer', ) print('Visualizer service initialized with id ' + visualizer.id) mongo = client.services.create( 'mongo', endpoint_spec=EndpointSpec(mode='vip', ports={27017: 27017}), mounts=['db:/data/db'], name='db', ) print('Mongo service initialized with id ' + mongo.id)
def run_service(service_name, image_name, command, restart_condition, networks, s_and_t, ports, mode='global', replicas=1): docker = MANAGER_CLIENR from dsp.image.valify import valify #if not valify(image_name): # return "找不到应用指定的镜像!" # Mount对象的集合 mounts = [] image_name = '192.168.123.251/'+image_name for s_t in s_and_t: type = False if s_t.get('read_only', '') == 'yes': type = True m = Mount(source=s_t.get('source', ''), target=s_t.get('target', ''), read_only=type) mounts.append(m) print s_t.get('source', '') #containSpec = ContainerSpec( image=image_name, mounts=mounts, command=command, tty=True, open_stdin=True) containSpec = ContainerSpec( image=image_name, command=command, tty=True, open_stdin=True) # 声明TaskTemplate--->task # restart_condition --->none, on - failure, or any restart_policy = RestartPolicy(condition=restart_condition) task = TaskTemplate(container_spec=containSpec, restart_policy=restart_policy) # 应用启动模式 if mode == "global": replicas = None service_mode = ServiceMode(mode=mode, replicas=replicas) # 接入点,包括负载均衡模式设置等 end_point = EndpointSpec(ports=ports) service_id = docker.create_service(task_template=task, name=service_name, mode=service_mode, networks=networks, endpoint_spec=end_point) return service_id
def scale_service(self, service_name, replica_count): try: service = self._get_service(service_name) service.update( mode=ServiceMode("replicated", replicas=replica_count)) except: pass
def test_scale_service_updates_the_service_replicas_to_given_replication_count( self): service = Mock() self.native_docker_client.services.list.return_value = [service] self.docker_client.scale_service("web", 3) self.native_docker_client.services.list.assert_called_once_with( filters=dict(name="web")) service.update.assert_called_once_with( mode=ServiceMode("replicated", replicas=3))
def createService(image, command, cpuRequirments, name, labels, selectedNodeId): client = docker.from_env() cpuRequirmentsInNanoSeconds = cpuRequirments * 1000000000 client.services.create( image, command, constraints=["node.role == worker", "node.id == " + selectedNodeId], mode=ServiceMode("replicated", 1), restart_policy=RestartPolicy(condition='none'), resources=Resources(cpu_reservation=cpuRequirmentsInNanoSeconds), name=name, labels = {"instance_name": labels.get("instance_name")}, hostname = selectedNodeId )
def scale(self, replicas): """ Scale service container. Args: replicas (int): The number of containers that should be running. Returns: bool: ``True`` if successful. """ if 'Global' in self.attrs['Spec']['Mode'].keys(): raise InvalidArgument('Cannot scale a global container') service_mode = ServiceMode('replicated', replicas) return self.client.api.update_service(self.id, self.version, mode=service_mode, fetch_current_spec=True)
def deploy(self, img: ImageSpec, env_vars, mounts, cargos, ports, cmd: list, name: str, tasks: int = 1, allow_probe=False): [self.load_vol(v, name) for v in cargos] self.assert_network() depl = self.find_depl(name) kwargs = self.cleaner( dict(name=name, endpoint_spec=dict(Ports=self.swarm_ports(ports)), networks=[DockerConst.NETWORK], mode=ServiceMode('replicated', replicas=tasks), task_template=TaskTemplate( force_update=5, resources=self.swarm_resources(), container_spec=ContainerSpec( command=cmd, image=img.target, env=env_vars, mounts=mounts + [v.mount for v in cargos], healthcheck=self.swarm_healthcheck(allow_probe))))) if depl is None: self.LOG.debug( "Creating container service '{}' with kwargs:".format(name)) self.LOG.debug(kwargs) return self.docker_api.create_service(**kwargs) else: kwargs.update(service=depl['ID'], version=depl['Version']['Index']) self.LOG.debug( "Updating container service '{}' with kwargs:".format(name)) self.LOG.debug(kwargs) return self.docker_api.update_service(**kwargs)
def create_jmeter_service(self, script_file, replicas): """ Creates jmeter service and runs it. This function first check if pre-requisite containers are running before starting the required number of jmeter with args. * influxdb is running * elasticsearch is running * kibana is running * logstash is running :param script_file: name of the script :param replicas: number of replicas :return: returns the (Service) """ # TODO influxdb is running # TODO elasticsearch is running # TODO kibana is running # TODO logstash is running try: jmeter = self.client.services.create( image='jmeter:' + JMETER_TAG, name='jmeter', command='jmeter.sh -n -t ./scripts/' + script_file + ' -j ./results/jmeter.log', mounts=[ SCRIPT_LOCATION + ':/opt/apache-jmeter-3.3/bin/scripts', RESULT_LOCATION + ':/opt/apache-jmeter-3.3/bin/results' ], networks=['juggernaut'], labels={'app': 'juggernaut'}, workdir='/opt/apache-jmeter-3.3/bin/', mode=ServiceMode(mode='replicated', replicas=replicas), update_config=UpdateConfig(parallelism=1, delay=60)) except APIError as e: print(e) else: return jmeter
def test_invalid_mode(self): with pytest.raises(InvalidArgument): ServiceMode('foobar')
def test_replicated_replicas_0(self): mode = ServiceMode('replicated', 0) assert mode == {'replicated': {'Replicas': 0}} assert mode.mode == 'replicated' assert mode.replicas == 0
def test_replicated_replicas(self): mode = ServiceMode('replicated', 21) assert mode == {'replicated': {'Replicas': 21}} assert mode.mode == 'replicated' assert mode.replicas == 21
def test_global_replicas_error(self): with pytest.raises(InvalidArgument): ServiceMode('global', 21)
def test_global_simple(self): mode = ServiceMode('global') assert mode == {'global': {}} assert mode.mode == 'global' assert mode.replicas is None
def test_replicated_simple(self): mode = ServiceMode('replicated') assert mode == {'replicated': {}} assert mode.mode == 'replicated' assert mode.replicas is None
def gen_director_service_params( # pylint: disable=unused-argument client: DockerClient, site_id: int, site_data: Dict[str, Any]) -> Dict[str, Any]: extra_env = { "PORT": "80", "HOST": "0.0.0.0", } params = gen_director_shared_params(client, site_id, site_data) env = params.pop("env", []) env.extend("{}={}".format(name, val) for name, val in extra_env.items()) # We do the run.sh path detection in the shell so that it can adapt to the path changing without # updating the Docker service # The killing of the child process is based off of # https://unix.stackexchange.com/a/146770/306760 shell_command = """date +'DIRECTOR: Starting server at %Y-%m-%d %H:%M:%S %Z' # See docs/UMASK.md before touching this umask "$1" for path in /site/run.sh /site/private/run.sh /site/public/run.sh; do if [ -x "$path" ]; then term() { date +'DIRECTOR: Stopping server at %Y-%m-%d %H:%M:%S %Z' kill "$child" } trap term TERM "$path" & child="$!" while ! wait; do true; done exec date +'DIRECTOR: Stopped server at %Y-%m-%d %H:%M:%S %Z' fi done echo 'DIRECTOR: No run.sh file found -- if it exists, make sure it is set as executable' exec sleep 2147483647""" params.update({ "name": get_director_service_name(site_id), "read_only": True, # See docs/UMASK.md before touching this "command": ["sh", "-c", shell_command, "sh", oct(settings.SITE_UMASK)[2:]], "workdir": "/site/public", "networks": ["director-sites"], "resources": Resources( # 0.1 CPUs, 100M or so of memory cpu_limit=convert_cpu_limit(site_data["resource_limits"]["cpus"]), mem_limit=convert_memory_limit( site_data["resource_limits"]["mem_limit"]), ), "env": env, "log_driver": "json-file", "log_driver_options": { # Keep minimal logs "max-size": "500k", "max-file": "1", }, "hosts": params.pop("extra_hosts"), "stop_grace_period": 3, "endpoint_spec": EndpointSpec(mode="vip", ports={}), "mode": ServiceMode(mode="replicated", replicas=1 if site_data["is_being_served"] else 0), "restart_policy": RestartPolicy(condition="any", delay=5, max_attempts=5, window=0), "update_config": UpdateConfig( parallelism=1, order="stop-first", failure_action="rollback", max_failure_ratio=0, # delay and monitor are in nanoseconds (1e9 seconds) delay=int(5 * (10**9)), monitor=int(5 * (10**9)), ), }) return params
def start(): print("/start\n", flush=True) # Get a dictionary of services currently running on the swarm existing_services = { service.name: service.id for service in client.services.list() } # Store reuse flag for this client's workflow lot_id = request.json['parking_lot_id'] lot_map[lot_id] = {} lot_map[lot_id]['reuse'] = request.json['reuse'] # Can store additional client-related data in this dict start_time = time.perf_counter() # Start requested services (if necessary) and scale them for service in request.json['services']: service_name = service['name'] replicas = service['replicas'] image_name = SERVICE_PARAMS[service_name]['image'] service_mode = ServiceMode('replicated', replicas) if service_name == 'cassandra': if SEED_NAME not in existing_services: # Create seed node print(SEED_NAME + " creating", flush=True) service = client.services.create( image_name, name=SEED_NAME, env=['CASSANDRA_BROADCAST_ADDRESS=' + SEED_NAME], networks=['parking-lot-net']) print(SEED_NAME + " created", flush=True) # Create the rest of the nodes and let them point to the seed node for i in range(1, replicas): j = (i % 3) + 1 DB_name = 'cassandra-' + str(j) DB_env = 'CASSANDRA_BROADCAST_ADDRESS=' + DB_name print(DB_name + " creating", flush=True) service = client.services.create( image_name, name=DB_name, env=[DB_env, 'CASSANDRA_SEEDS=' + SEED_NAME], networks=['parking-lot-net']) print(DB_name + " created", flush=True) else: if not request.json[ 'reuse']: # Append lot ID if reuse is not desired service_name = service_name + str( request.json['parking_lot_id']) print(service_name + " " + image_name + " creating", flush=True) if service_name in existing_services: service = client.services.get(existing_services[service_name]) else: service = client.services.create(image_name, name=service_name, networks=['parking-lot-net'], mode=service_mode) print(service_name + " " + image_name + " created", flush=True) end_time = time.perf_counter() print('Services deployment finished in ' + str(end_time - start_time) + ' sec', flush=True) # Confirm that all services are ready before returning success method to client MAX_ATTEMPTS = 30 attempt = 0 while attempt < MAX_ATTEMPTS: ready = True try: for service in request.json['services']: service_name = service['name'] if service_name != 'cassandra': port = SERVICE_PARAMS[service_name]['port'] if not request.json[ 'reuse']: # Append lot id if non-reuse case service_name = service_name + str( request.json['parking_lot_id']) print("attempting to check " + service_name, flush=True) url = 'http://' + service_name + ':' + port + '/is-alive' if not requests.get(url).json()['alive']: ready = False print(service_name + " connection failed", flush=True) if ready: available_time = time.perf_counter() print('Services are available in ' + str(available_time - start_time) + ' sec', flush=True) return jsonify(success=True) except: print( 'Failed to establish connection to a service. Trying again...') attempt += 1 sleep(SLEEP_TIME) return jsonify(success=False, message='Max retries exceeded')