mirror of https://github.com/docker/docker-py.git
				
				
				
			Ability to specify Host Devices during container start
The command line and daemon started supporting --device parameter during docker start a while ago in the following commit: docker/docker@e855c4b Since the command line looks like this, --device=[] Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc) This patch allows a list of strings to be passed into the start() method and we parse out the 3 components just like in the above mentioned commit
This commit is contained in:
		
							parent
							
								
									b93fca639e
								
							
						
					
					
						commit
						7a917cc7a0
					
				
							
								
								
									
										17
									
								
								README.md
								
								
								
								
							
							
						
						
									
										17
									
								
								README.md
								
								
								
								
							|  | @ -385,6 +385,23 @@ c.start(container_id, binds={ | |||
| }) | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| Access to devices on the host | ||||
| ============================= | ||||
| 
 | ||||
| If you need to directly expose some host devices to a container, you can use | ||||
| the devices parameter in the `Client.start` method as shown below | ||||
| 
 | ||||
| ```python | ||||
| c.start(container_id, devices=['/dev/sda:/dev/xvda:rwm']) | ||||
| ``` | ||||
| 
 | ||||
| Each string is a single mapping using the colon (':') as the separator. So the | ||||
| above example essentially allow the container to have read write permissions to | ||||
| access the host's /dev/sda via a node named /dev/xvda in the container. The | ||||
| devices parameter is a list to allow multiple devices to be mapped. | ||||
| 
 | ||||
| 
 | ||||
| Connection to daemon using HTTPS | ||||
| ================================ | ||||
| 
 | ||||
|  |  | |||
|  | @ -827,7 +827,7 @@ class Client(requests.Session): | |||
|     def start(self, container, binds=None, port_bindings=None, lxc_conf=None, | ||||
|               publish_all_ports=False, links=None, privileged=False, | ||||
|               dns=None, dns_search=None, volumes_from=None, network_mode=None, | ||||
|               restart_policy=None, cap_add=None, cap_drop=None): | ||||
|               restart_policy=None, cap_add=None, cap_drop=None, devices=None): | ||||
|         if isinstance(container, dict): | ||||
|             container = container.get('Id') | ||||
| 
 | ||||
|  | @ -895,6 +895,9 @@ class Client(requests.Session): | |||
|         if cap_drop: | ||||
|             start_config['CapDrop'] = cap_drop | ||||
| 
 | ||||
|         if devices: | ||||
|             start_config['Devices'] = utils.parse_devices(devices) | ||||
| 
 | ||||
|         url = self._url("/containers/{0}/start".format(container)) | ||||
|         res = self._post_json(url, data=start_config) | ||||
|         self._raise_for_status(res) | ||||
|  |  | |||
|  | @ -233,3 +233,23 @@ def parse_host(addr): | |||
|     if proto == "http+unix": | ||||
|         return "%s://%s" % (proto, host) | ||||
|     return "%s://%s:%d" % (proto, host, port) | ||||
| 
 | ||||
| 
 | ||||
| def parse_devices(devices): | ||||
|     device_list = [] | ||||
|     for device in devices: | ||||
|         device_mapping = device.split(",") | ||||
|         if device_mapping: | ||||
|             path_on_host = device_mapping[0] | ||||
|             if len(device_mapping) > 1: | ||||
|                 path_in_container = device_mapping[1] | ||||
|             else: | ||||
|                 path_in_container = path_on_host | ||||
|             if len(device_mapping) > 2: | ||||
|                 permissions = device_mapping[2] | ||||
|             else: | ||||
|                 permissions = 'rwm' | ||||
|             device_list.append({"PathOnHost": path_on_host, | ||||
|                                 "PathInContainer": path_in_container, | ||||
|                                 "CgroupPermissions": permissions}) | ||||
|     return device_list | ||||
|  |  | |||
|  | @ -891,6 +891,41 @@ class DockerClientTest(Cleanup, unittest.TestCase): | |||
|             docker.client.DEFAULT_TIMEOUT_SECONDS | ||||
|         ) | ||||
| 
 | ||||
|     def test_start_container_with_devices(self): | ||||
|         try: | ||||
|             self.client.start(fake_api.FAKE_CONTAINER_ID, | ||||
|                               devices=['/dev/sda:/dev/xvda:rwm', | ||||
|                                        '/dev/sdb:/dev/xvdb', | ||||
|                                        '/dev/sdc']) | ||||
|         except Exception as e: | ||||
|             self.fail('Command should not raise exception: {0}'.format(e)) | ||||
|         args = fake_request.call_args | ||||
|         self.assertEqual( | ||||
|             args[0][0], | ||||
|             url_prefix + 'containers/3cc2351ab11b/start' | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             json.loads(args[1]['data']), | ||||
|             {"PublishAllPorts": False, "Privileged": False, | ||||
|              "Devices": [{'CgroupPermissions': 'rwm', | ||||
|                           'PathInContainer': '/dev/sda:/dev/xvda:rwm', | ||||
|                           'PathOnHost': '/dev/sda:/dev/xvda:rwm'}, | ||||
|                          {'CgroupPermissions': 'rwm', | ||||
|                           'PathInContainer': '/dev/sdb:/dev/xvdb', | ||||
|                           'PathOnHost': '/dev/sdb:/dev/xvdb'}, | ||||
|                          {'CgroupPermissions': 'rwm', | ||||
|                           'PathInContainer': '/dev/sdc', | ||||
|                           'PathOnHost': '/dev/sdc'}]} | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             args[1]['headers'], | ||||
|             {'Content-Type': 'application/json'} | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             args[1]['timeout'], | ||||
|             docker.client.DEFAULT_TIMEOUT_SECONDS | ||||
|         ) | ||||
| 
 | ||||
|     def test_resize_container(self): | ||||
|         try: | ||||
|             self.client.resize( | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue