123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- from __future__ import absolute_import
- from __future__ import unicode_literals
- import logging
- from docker.errors import NotFound
- from .config import ConfigurationError
- log = logging.getLogger(__name__)
- class Volume(object):
- def __init__(self, client, project, name, driver=None, driver_opts=None,
- external_name=None):
- self.client = client
- self.project = project
- self.name = name
- self.driver = driver
- self.driver_opts = driver_opts
- self.external_name = external_name
- def create(self):
- return self.client.create_volume(
- self.full_name, self.driver, self.driver_opts
- )
- def remove(self):
- if self.external:
- log.info("Volume %s is external, skipping", self.full_name)
- return
- log.info("Removing volume %s", self.full_name)
- return self.client.remove_volume(self.full_name)
- def inspect(self):
- return self.client.inspect_volume(self.full_name)
- def exists(self):
- try:
- self.inspect()
- except NotFound:
- return False
- return True
- @property
- def external(self):
- return bool(self.external_name)
- @property
- def full_name(self):
- if self.external_name:
- return self.external_name
- return '{0}_{1}'.format(self.project, self.name)
- class ProjectVolumes(object):
- def __init__(self, volumes):
- self.volumes = volumes
- @classmethod
- def from_config(cls, name, config_data, client):
- config_volumes = config_data.volumes or {}
- volumes = {
- vol_name: Volume(
- client=client,
- project=name,
- name=vol_name,
- driver=data.get('driver'),
- driver_opts=data.get('driver_opts'),
- external_name=data.get('external_name')
- )
- for vol_name, data in config_volumes.items()
- }
- return cls(volumes)
- def remove(self):
- for volume in self.volumes.values():
- volume.remove()
- def initialize(self):
- try:
- for volume in self.volumes.values():
- volume_exists = volume.exists()
- if volume.external:
- log.debug(
- 'Volume {0} declared as external. No new '
- 'volume will be created.'.format(volume.name)
- )
- if not volume_exists:
- raise ConfigurationError(
- 'Volume {name} declared as external, but could'
- ' not be found. Please create the volume manually'
- ' using `{command}{name}` and try again.'.format(
- name=volume.full_name,
- command='docker volume create --name='
- )
- )
- continue
- if not volume_exists:
- log.info(
- 'Creating volume "{0}" with {1} driver'.format(
- volume.full_name, volume.driver or 'default'
- )
- )
- volume.create()
- else:
- driver = volume.inspect()['Driver']
- if volume.driver is not None and driver != volume.driver:
- raise ConfigurationError(
- 'Configuration for volume {0} specifies driver '
- '{1}, but a volume with the same name uses a '
- 'different driver ({3}). If you wish to use the '
- 'new configuration, please remove the existing '
- 'volume "{2}" first:\n'
- '$ docker volume rm {2}'.format(
- volume.name, volume.driver, volume.full_name,
- volume.inspect()['Driver']
- )
- )
- except NotFound:
- raise ConfigurationError(
- 'Volume %s specifies nonexistent driver %s' % (volume.name, volume.driver)
- )
- def namespace_spec(self, volume_spec):
- if not volume_spec.is_named_volume:
- return volume_spec
- volume = self.volumes[volume_spec.external]
- return volume_spec._replace(external=volume.full_name)
|