66
class JESNotSupported(Exception):
69
super(JESNotSupported, self).__init__(
70
'This client does not support JES')
73
class JESByDefault(Exception):
76
super(JESByDefault, self).__init__(
77
'This client does not need to enable JES')
65
80
def yaml_loads(yaml_str):
66
81
return yaml.safe_load(StringIO(yaml_str))
274
289
self.env.needs_sudo(), check=False, include_e=False,
275
290
timeout=timedelta(minutes=10).total_seconds())
277
jenv_path = get_jenv_path(get_juju_home(), self.env.environment)
292
jenv_path = get_jenv_path(self.juju_home, self.env.environment)
278
293
ensure_deleted(jenv_path)
280
295
def get_juju_output(self, command, *args, **kwargs):
352
367
if extra_env is not None:
353
368
env.update(extra_env)
355
return subprocess.check_call(args, env=env)
356
return subprocess.call(args, env=env)
370
call_func = subprocess.check_call
372
call_func = subprocess.call
373
return call_func(args, env=env)
359
376
def juju_async(self, command, args, include_e=True, timeout=None):
629
646
class EnvJujuClient25(EnvJujuClient):
648
def __init__(self, *args, **kwargs):
649
super(EnvJujuClient25, self).__init__(*args, **kwargs)
650
self._use_jes = False
652
def _supports_jes(self):
653
commands = self.get_juju_output('help', 'commands', include_e=False)
654
for line in commands.splitlines():
655
if line.startswith('system'):
659
def enable_jes(self):
662
if self._supports_jes():
665
if not self._supports_jes():
666
self._use_jes = False
667
raise JESNotSupported()
669
def _get_feature_flags(self):
670
if self.env.config.get('type') == 'cloudsigma':
672
if self._use_jes is True:
631
675
def _shell_environ(self):
632
676
"""Generate a suitable shell environment.
634
678
Juju's directory must be in the PATH to support plugins.
636
680
env = super(EnvJujuClient25, self)._shell_environ()
637
if self.env.config.get('type') == 'cloudsigma':
638
env[JUJU_DEV_FEATURE_FLAGS] = 'cloudsigma'
681
feature_flags = self._get_feature_flags()
682
env[JUJU_DEV_FEATURE_FLAGS] = ','.join(feature_flags)
642
686
class EnvJujuClient24(EnvJujuClient25):
644
"""Currently, same feature set as juju 25"""
687
"""Similar to EnvJujuClient25, but lacking JES support."""
689
def enable_jes(self):
690
raise JESNotSupported()
692
def _get_feature_flags(self):
693
if self.env.config.get('type') == 'cloudsigma':
647
697
def get_local_root(juju_home, env):
684
734
env.config[key] = env.config.get(key, default) + 1
737
def dump_environments_yaml(juju_home, config):
738
environments_path = get_environments_path(juju_home)
739
with open(environments_path, 'w') as config_file:
740
yaml.safe_dump(config, config_file)
688
744
def _temp_env(new_config, parent=None, set_home=True):
689
745
"""Use the supplied config as juju environment.
692
748
temp_bootstrap_env.
694
750
with temp_dir(parent) as temp_juju_home:
695
temp_environments = get_environments_path(temp_juju_home)
696
with open(temp_environments, 'w') as config_file:
697
yaml.safe_dump(new_config, config_file)
751
dump_environments_yaml(temp_juju_home, new_config)
699
753
context = scoped_environ()
705
759
yield temp_juju_home
709
def temp_bootstrap_env(juju_home, client, set_home=True):
762
def jes_home_path(juju_home, dir_name):
763
return os.path.join(juju_home, 'jes-homes', dir_name)
767
def make_jes_home(juju_home, dir_name, config):
768
home_path = jes_home_path(juju_home, dir_name)
769
if os.path.exists(home_path):
771
os.makedirs(home_path)
772
dump_environments_yaml(home_path, config)
777
def temp_bootstrap_env(juju_home, client, set_home=True, permanent=False):
710
778
"""Create a temporary environment for bootstrapping.
712
780
This involves creating a temporary juju home directory and returning its
742
810
"/var/lib/lxc", 2000000, "LXC containers")
743
811
new_config = {'environments': {client.env.environment: config}}
744
812
jenv_path = get_jenv_path(juju_home, client.env.environment)
745
with _temp_env(new_config, juju_home, set_home) as temp_juju_home:
814
context = make_jes_home(juju_home, client.env.environment, new_config)
816
context = _temp_env(new_config, juju_home, set_home)
817
with context as temp_juju_home:
746
818
if os.path.lexists(jenv_path):
747
819
raise Exception('%s already exists!' % jenv_path)
748
820
new_jenv_path = get_jenv_path(temp_juju_home, client.env.environment)
751
823
# partway through bootstrap.
752
824
ensure_dir(os.path.join(juju_home, 'environments'))
753
825
# Skip creating symlink where not supported (i.e. Windows).
754
if getattr(os, 'symlink', None) is not None:
826
if not permanent and getattr(os, 'symlink', None) is not None:
755
827
os.symlink(new_jenv_path, jenv_path)
756
828
old_juju_home = client.juju_home
757
829
client.juju_home = temp_juju_home
759
831
yield temp_juju_home
761
# replace symlink with file before deleting temp home.
763
os.rename(new_jenv_path, jenv_path)
765
if e.errno != errno.ENOENT:
767
# Remove dangling symlink
769
client.juju_home = old_juju_home
834
# replace symlink with file before deleting temp home.
836
os.rename(new_jenv_path, jenv_path)
838
if e.errno != errno.ENOENT:
840
# Remove dangling symlink
844
if e.errno != errno.ENOENT:
846
client.juju_home = old_juju_home