Add new volume commands: create, attach and detach
Change-Id: I2854e7f071108aa92e20bec9ca30ef9468aa383d
This commit is contained in:
		
							
								
								
									
										35
									
								
								almanachclient/commands/attach_volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								almanachclient/commands/attach_volume.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| # Copyright 2017 INAP | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| from dateutil import parser as date_parser | ||||
|  | ||||
| from cliff.command import Command | ||||
|  | ||||
|  | ||||
| class AttachVolumeCommand(Command): | ||||
|     """Attach volume""" | ||||
|  | ||||
|     def get_parser(self, prog_name): | ||||
|         parser = super().get_parser(prog_name) | ||||
|         parser.add_argument('volume_id', help='Volume ID') | ||||
|         parser.add_argument('--date', help='Start date') | ||||
|         parser.add_argument('--attachment', action='append', help='Instance attached to the volume') | ||||
|         return parser | ||||
|  | ||||
|     def take_action(self, parsed_args): | ||||
|         date = date_parser.parse(parsed_args.date) if parsed_args.date else None | ||||
|         self.app.get_client().attach_volume(parsed_args.volume_id, | ||||
|                                             attachments=parsed_args.attachment, | ||||
|                                             attachment_date=date) | ||||
|         return 'Success' | ||||
							
								
								
									
										44
									
								
								almanachclient/commands/create_volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								almanachclient/commands/create_volume.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| # Copyright 2017 INAP | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| from dateutil import parser as date_parser | ||||
|  | ||||
| from cliff.command import Command | ||||
|  | ||||
|  | ||||
| class CreateVolumeCommand(Command): | ||||
|     """Create volume""" | ||||
|  | ||||
|     def get_parser(self, prog_name): | ||||
|         parser = super().get_parser(prog_name) | ||||
|         parser.add_argument('tenant_id', help='Tenant ID') | ||||
|         parser.add_argument('volume_id', help='Volume ID') | ||||
|         parser.add_argument('volume_type_id', help='Volume type ID') | ||||
|         parser.add_argument('volume_name', help='Volume name') | ||||
|         parser.add_argument('volume_size', help='Volume size') | ||||
|         parser.add_argument('--start', help='Start date') | ||||
|         parser.add_argument('--attachment', action='append', help='Instance attached to the volume') | ||||
|         return parser | ||||
|  | ||||
|     def take_action(self, parsed_args): | ||||
|         start_date = date_parser.parse(parsed_args.start) if parsed_args.start else None | ||||
|  | ||||
|         self.app.get_client().create_volume(parsed_args.tenant_id, | ||||
|                                             parsed_args.volume_id, | ||||
|                                             parsed_args.volume_type_id, | ||||
|                                             parsed_args.volume_name, | ||||
|                                             parsed_args.volume_size, | ||||
|                                             attachments=parsed_args.attachment, | ||||
|                                             start=start_date) | ||||
|         return 'Success' | ||||
							
								
								
									
										35
									
								
								almanachclient/commands/detach_volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								almanachclient/commands/detach_volume.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| # Copyright 2017 INAP | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| from dateutil import parser as date_parser | ||||
|  | ||||
| from cliff.command import Command | ||||
|  | ||||
|  | ||||
| class DetachVolumeCommand(Command): | ||||
|     """Detach volume""" | ||||
|  | ||||
|     def get_parser(self, prog_name): | ||||
|         parser = super().get_parser(prog_name) | ||||
|         parser.add_argument('volume_id', help='Volume ID') | ||||
|         parser.add_argument('--date', help='Start date') | ||||
|         parser.add_argument('--attachment', action='append', help='Instance attached to the volume') | ||||
|         return parser | ||||
|  | ||||
|     def take_action(self, parsed_args): | ||||
|         date = date_parser.parse(parsed_args.date) if parsed_args.date else None | ||||
|         self.app.get_client().detach_volume(parsed_args.volume_id, | ||||
|                                             attachments=parsed_args.attachment, | ||||
|                                             attachment_date=date) | ||||
|         return 'Success' | ||||
| @@ -18,10 +18,13 @@ import sys | ||||
| from cliff import app | ||||
| from cliff import commandmanager | ||||
|  | ||||
| from almanachclient.commands.attach_volume import AttachVolumeCommand | ||||
| from almanachclient.commands.create_instance import CreateInstanceCommand | ||||
| from almanachclient.commands.create_volume import CreateVolumeCommand | ||||
| from almanachclient.commands.create_volume_type import CreateVolumeTypeCommand | ||||
| from almanachclient.commands.delete_instance import DeleteInstanceCommand | ||||
| from almanachclient.commands.delete_volume_type import DeleteVolumeTypeCommand | ||||
| from almanachclient.commands.detach_volume import DetachVolumeCommand | ||||
| from almanachclient.commands.endpoint import EndpointCommand | ||||
| from almanachclient.commands.get_entity import GetEntityCommand | ||||
| from almanachclient.commands.get_volume_type import GetVolumeTypeCommand | ||||
| @@ -47,7 +50,10 @@ class AlmanachCommandManager(commandmanager.CommandManager): | ||||
|         'list-volume-types': ListVolumeTypeCommand, | ||||
|         'get-volume-type': GetVolumeTypeCommand, | ||||
|         'list-volumes': ListVolumeCommand, | ||||
|         'create-volume': CreateVolumeCommand, | ||||
|         'resize-volume': ResizeVolumeCommand, | ||||
|         'attach-volume': AttachVolumeCommand, | ||||
|         'detach-volume': DetachVolumeCommand, | ||||
|         'list-instances': ListInstanceCommand, | ||||
|         'create-instance': CreateInstanceCommand, | ||||
|         'delete-instance': DeleteInstanceCommand, | ||||
|   | ||||
							
								
								
									
										47
									
								
								almanachclient/tests/commands/test_attach_volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								almanachclient/tests/commands/test_attach_volume.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| # Copyright 2017 INAP | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| from argparse import Namespace | ||||
| import datetime | ||||
| from unittest import mock | ||||
|  | ||||
| from almanachclient.commands.attach_volume import AttachVolumeCommand | ||||
|  | ||||
| from almanachclient.tests import base | ||||
|  | ||||
|  | ||||
| class TestAttachVolumeCommand(base.TestCase): | ||||
|  | ||||
|     def setUp(self): | ||||
|         super().setUp() | ||||
|         self.app = mock.Mock() | ||||
|         self.app_args = mock.Mock() | ||||
|         self.args = Namespace(volume_id='some uuid', attachment=['vm1', 'vm2'], date=None) | ||||
|  | ||||
|         self.client = mock.Mock() | ||||
|         self.app.get_client.return_value = self.client | ||||
|         self.command = AttachVolumeCommand(self.app, self.app_args) | ||||
|  | ||||
|     def test_execute_command(self): | ||||
|         self.assertEqual('Success', self.command.take_action(self.args)) | ||||
|         self.client.attach_volume.assert_called_once_with('some uuid', | ||||
|                                                           attachments=['vm1', 'vm2'], | ||||
|                                                           attachment_date=None) | ||||
|  | ||||
|     def test_execute_command_with_date(self): | ||||
|         self.args.date = '2017-01-01' | ||||
|         self.assertEqual('Success', self.command.take_action(self.args)) | ||||
|         self.client.attach_volume.assert_called_once_with('some uuid', | ||||
|                                                           attachments=['vm1', 'vm2'], | ||||
|                                                           attachment_date=datetime.datetime(2017, 1, 1, 0, 0)) | ||||
							
								
								
									
										50
									
								
								almanachclient/tests/commands/test_create_volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								almanachclient/tests/commands/test_create_volume.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| # Copyright 2017 INAP | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| from argparse import Namespace | ||||
| import datetime | ||||
| from unittest import mock | ||||
|  | ||||
| from almanachclient.commands.create_volume import CreateVolumeCommand | ||||
|  | ||||
| from almanachclient.tests import base | ||||
|  | ||||
|  | ||||
| class TestCreateVolumeCommand(base.TestCase): | ||||
|  | ||||
|     def setUp(self): | ||||
|         super().setUp() | ||||
|         self.app = mock.Mock() | ||||
|         self.app_args = mock.Mock() | ||||
|         self.args = Namespace(tenant_id='tenant uuid', | ||||
|                               volume_id='volume uuid', | ||||
|                               volume_type_id='volume type uuid', | ||||
|                               volume_name='volume', | ||||
|                               volume_size=2, | ||||
|                               start='2017-01-01', | ||||
|                               attachment=None) | ||||
|  | ||||
|         self.client = mock.Mock() | ||||
|         self.app.get_client.return_value = self.client | ||||
|         self.command = CreateVolumeCommand(self.app, self.app_args) | ||||
|  | ||||
|     def test_execute_command(self): | ||||
|         self.assertEqual('Success', self.command.take_action(self.args)) | ||||
|         self.client.create_volume.assert_called_once_with('tenant uuid', | ||||
|                                                           'volume uuid', | ||||
|                                                           'volume type uuid', | ||||
|                                                           'volume', | ||||
|                                                           2, | ||||
|                                                           start=datetime.datetime(2017, 1, 1, 0, 0), | ||||
|                                                           attachments=None) | ||||
							
								
								
									
										47
									
								
								almanachclient/tests/commands/test_detach_volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								almanachclient/tests/commands/test_detach_volume.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| # Copyright 2017 INAP | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| from argparse import Namespace | ||||
| import datetime | ||||
| from unittest import mock | ||||
|  | ||||
| from almanachclient.commands.detach_volume import DetachVolumeCommand | ||||
|  | ||||
| from almanachclient.tests import base | ||||
|  | ||||
|  | ||||
| class TestDetachVolumeCommand(base.TestCase): | ||||
|  | ||||
|     def setUp(self): | ||||
|         super().setUp() | ||||
|         self.app = mock.Mock() | ||||
|         self.app_args = mock.Mock() | ||||
|         self.args = Namespace(volume_id='some uuid', attachment=['vm1', 'vm2'], date=None) | ||||
|  | ||||
|         self.client = mock.Mock() | ||||
|         self.app.get_client.return_value = self.client | ||||
|         self.command = DetachVolumeCommand(self.app, self.app_args) | ||||
|  | ||||
|     def test_execute_command(self): | ||||
|         self.assertEqual('Success', self.command.take_action(self.args)) | ||||
|         self.client.detach_volume.assert_called_once_with('some uuid', | ||||
|                                                           attachments=['vm1', 'vm2'], | ||||
|                                                           attachment_date=None) | ||||
|  | ||||
|     def test_execute_command_with_date(self): | ||||
|         self.args.date = '2017-01-01' | ||||
|         self.assertEqual('Success', self.command.take_action(self.args)) | ||||
|         self.client.detach_volume.assert_called_once_with('some uuid', | ||||
|                                                           attachments=['vm1', 'vm2'], | ||||
|                                                           attachment_date=datetime.datetime(2017, 1, 1, 0, 0)) | ||||
| @@ -250,3 +250,58 @@ class TestClient(base.TestCase): | ||||
|                                          data=json.dumps({'size': 3, | ||||
|                                                           'date': date.strftime(Client.DATE_FORMAT_BODY)}), | ||||
|                                          headers=self.headers) | ||||
|  | ||||
|     @mock.patch('requests.post') | ||||
|     def test_create_volume(self, requests): | ||||
|         date = datetime.now() | ||||
|         requests.return_value = self.response | ||||
|  | ||||
|         self.response.headers['Content-Length'] = 0 | ||||
|         self.response.status_code = 201 | ||||
|  | ||||
|         self.assertTrue(self.client.create_volume('tenant_id', 'my_volume_id', 'volume_type_id', | ||||
|                                                   'volume name', 2, start=date)) | ||||
|  | ||||
|         requests.assert_called_once_with('{}{}'.format(self.url, '/v1/project/tenant_id/volume'), | ||||
|                                          params=None, | ||||
|                                          data=json.dumps({ | ||||
|                                              'volume_id': 'my_volume_id', | ||||
|                                              'volume_type': 'volume_type_id', | ||||
|                                              'volume_name': 'volume name', | ||||
|                                              'size': 2, | ||||
|                                              'attached_to': [], | ||||
|                                              'start': date.strftime(Client.DATE_FORMAT_BODY), | ||||
|                                          }), | ||||
|                                          headers=self.headers) | ||||
|  | ||||
|     @mock.patch('requests.put') | ||||
|     def test_attach_volume(self, requests): | ||||
|         date = datetime.now() | ||||
|         requests.return_value = self.response | ||||
|  | ||||
|         self.response.headers['Content-Length'] = 0 | ||||
|         self.response.status_code = 200 | ||||
|  | ||||
|         self.assertTrue(self.client.attach_volume('my_volume_id', ['instance_id'], date)) | ||||
|  | ||||
|         requests.assert_called_once_with('{}{}'.format(self.url, '/v1/volume/my_volume_id/attach'), | ||||
|                                          params=None, | ||||
|                                          data=json.dumps({'attachments': ['instance_id'], | ||||
|                                                           'date': date.strftime(Client.DATE_FORMAT_BODY)}), | ||||
|                                          headers=self.headers) | ||||
|  | ||||
|     @mock.patch('requests.put') | ||||
|     def test_detach_volume(self, requests): | ||||
|         date = datetime.now() | ||||
|         requests.return_value = self.response | ||||
|  | ||||
|         self.response.headers['Content-Length'] = 0 | ||||
|         self.response.status_code = 200 | ||||
|  | ||||
|         self.assertTrue(self.client.detach_volume('my_volume_id', ['instance_id'], date)) | ||||
|  | ||||
|         requests.assert_called_once_with('{}{}'.format(self.url, '/v1/volume/my_volume_id/detach'), | ||||
|                                          params=None, | ||||
|                                          data=json.dumps({'attachments': ['instance_id'], | ||||
|                                                           'date': date.strftime(Client.DATE_FORMAT_BODY)}), | ||||
|                                          headers=self.headers) | ||||
|   | ||||
| @@ -85,6 +85,31 @@ class Client(HttpClient): | ||||
|         params = {'start': self._format_qs_datetime(start), 'end': self._format_qs_datetime(end)} | ||||
|         return self._get(url, params) | ||||
|  | ||||
|     def create_volume(self, tenant_id, volume_id, volume_type_id, name, size, attachments=None, start=None): | ||||
|         """Create a volume. | ||||
|  | ||||
|         :arg str tenant_id: Tenant UUID | ||||
|         :arg str volume_id: Volume UUID | ||||
|         :arg str volume_type_id: Volume type | ||||
|         :arg str name: Volume name | ||||
|         :arg int size: Volume size | ||||
|         :arg list attachments: List of instance attached to the volume | ||||
|         :arg datetime start: Creation date or now if None | ||||
|         :raises: ClientError | ||||
|         :rtype: bool | ||||
|         """ | ||||
|         data = { | ||||
|             'volume_id': volume_id, | ||||
|             'volume_type': volume_type_id, | ||||
|             'volume_name': name, | ||||
|             'size': size, | ||||
|             'attached_to': attachments or [], | ||||
|             'start': self._format_body_datetime(start or datetime.now()), | ||||
|         } | ||||
|  | ||||
|         self._post('{}/{}/project/{}/volume'.format(self.url, self.api_version, tenant_id), data=data) | ||||
|         return True | ||||
|  | ||||
|     def resize_volume(self, volume_id, size, resize_date=None): | ||||
|         """Resize a volume. | ||||
|  | ||||
| @@ -102,6 +127,40 @@ class Client(HttpClient): | ||||
|         self._put('{}/{}/volume/{}/resize'.format(self.url, self.api_version, volume_id), data=data) | ||||
|         return True | ||||
|  | ||||
|     def attach_volume(self, volume_id, attachments, attachment_date=None): | ||||
|         """Attach instances to a volume. | ||||
|  | ||||
|         :arg str volume_id: Volume UUID | ||||
|         :arg list attachments: List of instance ID | ||||
|         :arg datetime attachment_date: Attachment date | ||||
|         :raises: ClientError | ||||
|         :rtype: bool | ||||
|         """ | ||||
|         data = { | ||||
|             'attachments': attachments, | ||||
|             'date': self._format_body_datetime(attachment_date or datetime.now()), | ||||
|         } | ||||
|  | ||||
|         self._put('{}/{}/volume/{}/attach'.format(self.url, self.api_version, volume_id), data=data) | ||||
|         return True | ||||
|  | ||||
|     def detach_volume(self, volume_id, attachments, attachment_date=None): | ||||
|         """Detach instances from a volume. | ||||
|  | ||||
|         :arg str volume_id: Volume UUID | ||||
|         :arg list attachments: List of instance ID | ||||
|         :arg datetime attachment_date: Attachment date | ||||
|         :raises: ClientError | ||||
|         :rtype: bool | ||||
|         """ | ||||
|         data = { | ||||
|             'attachments': attachments, | ||||
|             'date': self._format_body_datetime(attachment_date or datetime.now()), | ||||
|         } | ||||
|  | ||||
|         self._put('{}/{}/volume/{}/detach'.format(self.url, self.api_version, volume_id), data=data) | ||||
|         return True | ||||
|  | ||||
|     def get_instances(self, tenant_id, start, end): | ||||
|         """List instances for a tenant. | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,14 @@ | ||||
| Installation | ||||
| ============ | ||||
|  | ||||
| The client requires at least the version 4.0.9 of Almanach. | ||||
| Requirements | ||||
| ------------ | ||||
|  | ||||
| - Python >= 3.4 | ||||
| - Almanach >= 4.0.9 | ||||
|  | ||||
| Instructions | ||||
| ------------ | ||||
|  | ||||
| At the command line:: | ||||
|  | ||||
|   | ||||
| @@ -208,6 +208,35 @@ Arguments: | ||||
| * :code:`start`: Start date (ISO8601 format) | ||||
| * :code:`end`: End date (ISO8601 format) | ||||
|  | ||||
| Create Volume | ||||
| ------------- | ||||
|  | ||||
| Usage: :code:`almanach create-volume <tenant_id> <volume_id> <volume_type_id> <volume_name> <size> --date <creation_date> --attachment <instance_id>` | ||||
|  | ||||
| .. code:: bash | ||||
|  | ||||
|     almanach create-volume \ | ||||
|         8c3bc3aa-28d6-4863-b5ae-72e1b415f79d \ | ||||
|         3e3b22e6-a10c-4c00-b8e5-05fcc8422b11 \ | ||||
|         f3786e9f-f8e6-4944-a3bc-e11b9f112706 \ | ||||
|         my-volume \ | ||||
|         5 \ | ||||
|         --attachment=86dd5189-d9d6-40f7-a319-19231fbd4e07 \ | ||||
|         --attachment=252e49d8-abf2-486c-8478-b5f775134f54 | ||||
|  | ||||
|     Success | ||||
|  | ||||
| Arguments: | ||||
|  | ||||
| * :code:`tenant_id`: Tenant ID (UUID) | ||||
| * :code:`volume_id`: Volume ID (UUID) | ||||
| * :code:`volume_type_id`: Volume ID (UUID) | ||||
| * :code:`volume_name`: Volume name (string) | ||||
| * :code:`size`: Volume size (integer) | ||||
| * :code:`date`: Creation date (ISO8601 format), if not specified the current datetime is used | ||||
| * :code:`attachment`: Attach the volume to one or many instances (UUID) | ||||
|  | ||||
|  | ||||
| Resize Volume | ||||
| ------------- | ||||
|  | ||||
| @@ -225,6 +254,45 @@ Arguments: | ||||
| * :code:`size`: Volume size (integer) | ||||
| * :code:`date`: Resize date (ISO8601 format), if not specified the current datetime is used | ||||
|  | ||||
| Attach Volume | ||||
| ------------- | ||||
|  | ||||
| Usage: :code:`almanach attach-volume <volume_id> --date <creation_date> --attachment <instance_id>` | ||||
|  | ||||
| .. code:: bash | ||||
|  | ||||
|     almanach attach-volume \ | ||||
|         8c3bc3aa-28d6-4863-b5ae-72e1b415f79d \ | ||||
|         --attachment=86dd5189-d9d6-40f7-a319-19231fbd4e07 | ||||
|  | ||||
|     Success | ||||
|  | ||||
| Arguments: | ||||
|  | ||||
| * :code:`volume_id`: Volume ID (UUID) | ||||
| * :code:`date`: Attachment date (ISO8601 format), if not specified the current datetime is used | ||||
| * :code:`attachment`: Attach the volume to one or many instances (UUID) | ||||
|  | ||||
|  | ||||
| Detach Volume | ||||
| ------------- | ||||
|  | ||||
| Usage: :code:`almanach detach-volume <volume_id> --date <creation_date> --attachment <instance_id>` | ||||
|  | ||||
| .. code:: bash | ||||
|  | ||||
|     almanach detach-volume \ | ||||
|         8c3bc3aa-28d6-4863-b5ae-72e1b415f79d \ | ||||
|         --attachment=86dd5189-d9d6-40f7-a319-19231fbd4e07 | ||||
|  | ||||
|     Success | ||||
|  | ||||
| Arguments: | ||||
|  | ||||
| * :code:`volume_id`: Volume ID (UUID) | ||||
| * :code:`date`: Attachment date (ISO8601 format), if not specified the current datetime is used | ||||
| * :code:`attachment`: Attach the volume to one or many instances (UUID) | ||||
|  | ||||
| List Volume Types | ||||
| ----------------- | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Frédéric Guillot
					Frédéric Guillot