Package VMBuilder :: Package plugins
[frames] | no frames]

Source Code for Package VMBuilder.plugins

  1  # 
  2  #    Uncomplicated VM Builder 
  3  #    Copyright (C) 2007-2009 Canonical Ltd. 
  4  # 
  5  #    See AUTHORS for list of contributors 
  6  # 
  7  #    This program is free software: you can redistribute it and/or modify 
  8  #    it under the terms of the GNU General Public License version 3, as 
  9  #    published by the Free Software Foundation. 
 10  # 
 11  #    This program is distributed in the hope that it will be useful, 
 12  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  #    GNU General Public License for more details. 
 15  # 
 16  #    You should have received a copy of the GNU General Public License 
 17  #    along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 18  # 
 19  import os 
 20  import re 
 21  import shutil 
 22   
 23  import VMBuilder 
 24  import VMBuilder.util as util 
 25  from VMBuilder.exception import VMBuilderException 
 26   
27 -def load_plugins():
28 for plugin in find_plugins(): 29 exec "import %s" % plugin
30
31 -def find_plugins():
32 retval = [] 33 for plugin_dir in __path__: 34 for p in os.listdir(plugin_dir): 35 path = '%s/%s' % (plugin_dir, p) 36 if os.path.isdir(path) and os.path.isfile('%s/__init__.py' % path): 37 retval.append("VMBuilder.plugins.%s" % p) 38 return retval
39
40 -class Plugin(object):
41 priority = 10 42
43 - def __init__(self, context):
44 self.context = context 45 self._setting_groups = [] 46 self.register_options()
47
48 - def register_options(self):
49 pass
50
51 - def set_defaults(self):
52 pass
53
54 - def preflight_check(self):
55 """ 56 Override this method with checks for anything that might cause the VM creation to fail 57 58 raise an exception if you can see already that this won't work 59 """ 60 pass
61
62 - def post_install(self):
63 """ 64 This is called just after the distro is installed, before it gets copied to the fs images. 65 """ 66 pass
67
68 - def install_file(self, path, contents=None, source=None, mode=None):
69 fullpath = '%s%s' % (self.context.chroot_dir, path) 70 if not os.path.isdir(os.path.dirname(fullpath)): 71 os.makedirs(os.path.dirname(fullpath)) 72 if source and not contents: 73 shutil.copy(source, fullpath) 74 else: 75 fp = open(fullpath, 'w') 76 fp.write(contents) 77 fp.close() 78 if mode: 79 os.chmod(fullpath, mode) 80 return fullpath
81
82 - def install_from_template(self, path, tmplname, context=None, mode=None):
83 return self.install_file(path, VMBuilder.util.render_template(self.__module__.split('.')[2], self.context, tmplname, context), mode=mode)
84
85 - def run_in_target(self, *args, **kwargs):
86 return util.run_cmd('chroot', self.chroot_dir, *args, **kwargs)
87
88 - def call_hooks(self, *args, **kwargs):
89 return util.call_hooks(self.context, *args, **kwargs)
90 91 # Settings
92 - class SettingGroup(object):
93 - def __init__(self, plugin, context, name):
94 # The plugin that owns this setting 95 self.plugin = plugin 96 # The VM object 97 self.context = context 98 # Name of the Setting Group 99 self.name = name 100 # A list of Setting objects 101 self._settings = []
102
103 - def add_setting(self, *args, **kwargs):
104 # kwarg['type'] is used to determine which type of Setting object to create 105 # but we don't want to pass it on to its __init__. 106 if 'type' in kwargs: 107 type = kwargs['type'] 108 del kwargs['type'] 109 else: 110 type = 'str' 111 112 if type == 'str': 113 setting = self.plugin.StringSetting(self, *args, **kwargs) 114 elif type == 'bool': 115 setting = self.plugin.BooleanSetting(self, *args, **kwargs) 116 elif type == 'list': 117 setting = self.plugin.ListSetting(self, *args, **kwargs) 118 elif type == 'int': 119 setting = self.plugin.IntSetting(self, *args, **kwargs) 120 else: 121 raise VMBuilderException("Unknown setting type: '%s' (Plugin: '%s', Setting group: '%s', Setting: '%s')" % 122 (type, 123 self.plugin.__module__, 124 self.name, 125 args[0])) 126 self._settings.append(setting)
127
128 - class Setting(object):
129 default = None 130
131 - def __init__(self, setting_group, name, metavar=None, help=None, extra_args=None, valid_options=None, action=None, **kwargs):
132 # The Setting Group object that owns this Setting 133 self.setting_group = setting_group 134 # The name if the setting 135 name_regex = '[a-z0-9-]+$' 136 if not re.match(name_regex, name): 137 raise VMBuilderException('Invalid name for Setting: %s. Must match regex: %s' % (name, name_regex)) 138 else: 139 self.name = name 140 141 self.default = kwargs.get('default', self.default) 142 self.help = help 143 # Alternate names (for the CLI) 144 self.extra_args = extra_args or [] 145 self.metavar = metavar 146 self.value = None 147 self.value_set = False 148 self.valid_options = valid_options 149 150 if self.name in self.setting_group.context._config: 151 raise VMBuilderException("Setting named %s already exists. Previous definition in %s/%s/%s." % 152 (self.name, 153 self.setting_group.plugin.__name__, 154 self.setting_group.plugin._config[self.name].setting_group.name, 155 self.setting_group.plugin._config[self.name].name)) 156 157 self.setting_group.context._config[self.name] = self
158
159 - def get_value(self):
160 """ 161 If a value has previously been set, return it. 162 If not, return the default value. 163 """ 164 165 if self.value_set: 166 return self.value 167 else: 168 return self.default
169
170 - def do_check_value(self, value):
171 """ 172 Checks the value's validity. 173 """ 174 if self.valid_options is not None: 175 if value not in self.valid_options: 176 raise VMBuilderException('%r is not a valid option for %s. Valid options are: %s' % (value, self.name, ' '.join(self.valid_options))) 177 else: 178 return self.check_value(value)
179
180 - def get_valid_options(self):
181 return self.valid_options
182
183 - def set_valid_options(self, valid_options):
184 """ 185 Set the list of valid options for this setting. 186 """ 187 if not type(valid_options) == list and valid_options is not None: 188 raise VMBuilderException('set_valid_options only accepts lists or None') 189 if valid_options: 190 for option in valid_options: 191 self.check_value(option) 192 self.valid_options = valid_options
193
194 - def get_default(self):
195 """ 196 Return the default value. 197 """ 198 return self.default
199
200 - def set_default(self, value):
201 """ 202 Set a new default value. 203 """ 204 value = self.do_check_value(value) 205 self.default = value
206
207 - def set_value_fuzzy(self, value):
208 """ 209 Set new value. 210 211 Contrary to L{set_value}, L{set_value_fuzzy} will attempt 212 to turn L{value} into the target type. E.g. turning '10' 213 into 10, "main,universe,multiverse" into ['main', 214 'universe', 'multiverse'] 215 """ 216 return self.set_value(value)
217
218 - def set_value(self, value):
219 """ 220 Set a new value. 221 """ 222 value = self.do_check_value(value) 223 self.value = value 224 self.value_set = True
225
226 - class ListSetting(Setting):
227 - def __init__(self, *args, **kwargs):
228 self.default = [] 229 super(Plugin.ListSetting, self).__init__(*args, **kwargs)
230
231 - def set_value_fuzzy(self, value):
232 if len(value) == 1 and type(value[0]) == str: 233 value = value[0] 234 if type(value) == str: 235 if value == '': 236 return self.set_value([]) 237 for sep in [':', ',']: 238 if sep in value: 239 split_regex = re.compile("\s*%s\s*" % sep) 240 return self.set_value(split_regex.split(value)) 241 value = [value] 242 self.set_value(value) 243 return self.set_value(value)
244
245 - def check_value(self, value):
246 if not type(value) == list: 247 raise VMBuilderException('%r is type %s, expected list.' % (value, type(value))) 248 return value
249
250 - class IntSetting(Setting):
251 - def set_value_fuzzy(self, value):
252 if type(value) != int: 253 try: 254 value = int(value) 255 except ValueError: 256 raise VMBuilderException('Could not interpret %r as an int.' % (value,)) 257 return self.set_value(value)
258
259 - def check_value(self, value):
260 if not type(value) == int: 261 raise VMBuilderException('%r is type %s, expected int.' % (value, type(value))) 262 return value
263
264 - class BooleanSetting(Setting):
265 - def set_value_fuzzy(self, value):
266 if type(value) == str: 267 if value.lower() in ['no', 'false', 'off', '0']: 268 value = False 269 elif value.lower() in ['yes', 'true', 'on', '1']: 270 value = True 271 else: 272 raise VMBuilderException('Could not interpret %r as a boolean value.' % (value,)) 273 return self.set_value(value)
274
275 - def check_value(self, value):
276 if not type(value) == bool: 277 raise VMBuilderException('%r is type %s, expected bool.' % (value, type(value))) 278 return value
279
280 - class StringSetting(Setting):
281 - def check_value(self, value):
282 if not type(value) == str: 283 raise VMBuilderException('%r is type %s, expected str.' % (value, type(value))) 284 return value
285
286 - def setting_group(self, name):
287 setting_group = self.SettingGroup(self, self.context, name) 288 self._setting_groups.append(setting_group) 289 return setting_group
290
291 - def has_setting(self, name):
292 return name in self.context._config
293
294 - def get_setting(self, name):
295 if not name in self.context._config: 296 raise VMBuilderException('Unknown config key: %s' % name) 297 return self.context._config[name].get_value()
298
299 - def set_setting_fuzzy(self, name, value):
300 if not name in self.context._config: 301 raise VMBuilderException('Unknown config key: %s' % name) 302 # print 'fuzzy setting of %s: %r' % (name, value) 303 self.context._config[name].set_value_fuzzy(value)
304
305 - def set_setting(self, name, value):
306 if not name in self.context._config: 307 raise VMBuilderException('Unknown config key: %s' % name) 308 self.context._config[name].set_value(value)
309
310 - def set_setting_default(self, name, value):
311 if not name in self.context._config: 312 raise VMBuilderException('Unknown config key: %s' % name) 313 self.context._config[name].set_default(value)
314
315 - def get_setting_default(self, name):
316 if not name in self.context._config: 317 raise VMBuilderException('Unknown config key: %s' % name) 318 return self.context._config[name].get_default()
319
320 - def get_setting_valid_options(self, name):
321 if not name in self.context._config: 322 raise VMBuilderException('Unknown config key: %s' % name) 323 return self.context._config[name].get_valid_options()
324
325 - def set_setting_valid_options(self, name, valid_options):
326 if not name in self.context._config: 327 raise VMBuilderException('Unknown config key: %s' % name) 328 self.context._config[name].set_valid_options(valid_options)
329