def initialize(self): """ Initialize this prefix, this includes creating the destination path, and creating the uuid for the prefix, for any other actions see :func:`Prefix.virt_conf` Will safely roll back if any of those steps fail Returns: None Raises: RuntimeError: If it fails to create the prefix dir """ prefix = self.paths.prefix os.environ['LAGO_PREFIX_PATH'] = prefix os.environ['LAGO_WORKDIR_PATH'] = os.path.dirname(prefix) with utils.RollbackContext() as rollback: with LogTask('Create prefix dirs'): try: os.mkdir(prefix) except OSError as error: raise RuntimeError( 'Could not create prefix at %s:\n%s' % (prefix, error) ) rollback.prependDefer(shutil.rmtree, prefix) with open(self.paths.uuid(), 'w') as f, \ LogTask('Generate prefix uuid'): f.write(uuid.uuid1().hex) with LogTask('Create ssh keys'): self._create_ssh_keys() with LogTask('Tag prefix as initialized'): with open(self.paths.prefix_lagofile(), 'w') as fd: fd.write('') rollback.clear()
def virt_conf( self, conf, template_repo=None, template_store=None, ): with utils.RollbackContext() as rollback: if not os.path.exists(self.paths.images()): os.mkdir(self.paths.images()) rollback.prependDefer(os.unlink, self.paths.images()) if not os.path.exists(self.paths.virt()): os.mkdir(self.paths.virt()) rollback.prependDefer(os.unlink, self.paths.virt()) self._config_net_topology(conf) for name, spec in conf['domains'].items(): new_disks = [] spec['name'] = name for disk in spec['disks']: path, metadata = self._create_disk( name, disk, template_repo, template_store, ) new_disks.append( { 'path': path, 'dev': disk['dev'], 'format': disk['format'], 'metadata': metadata, }, ) conf['domains'][name]['disks'] = new_disks env = virt.VirtEnv(self, conf['domains'], conf['nets']) env.save() env.bootstrap() rollback.clear()
def test_vm_lifecycle(self): inst = kimchi.model.Model(objstore_loc=self.tmp_store) with utils.RollbackContext() as rollback: params = {'name': 'test', 'disks': []} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': 'kimchi-vm', 'template': '/templates/test'} inst.vms_create(params) rollback.prependDefer(inst.vm_delete, 'kimchi-vm') vms = inst.vms_get_list() self.assertTrue('kimchi-vm' in vms) inst.vm_start('kimchi-vm') rollback.prependDefer(inst.vm_stop, 'kimchi-vm') info = inst.vm_lookup('kimchi-vm') self.assertEquals('running', info['state']) vms = inst.vms_get_list() self.assertFalse('kimchi-vm' in vms)
def _config_net_topology(self, conf): all_nics = [(nic, dom_name) for dom_name, dom in conf['domains'].items() for nic in dom['nics']] nics_by_net = {} for nic, dom in all_nics: nics_by_net.setdefault(nic['net'], []).append((nic, dom)) with utils.RollbackContext() as rollback: for net_name, net_spec in conf.get('nets', {}).items(): net_spec['name'] = net_name if net_spec.setdefault('type', 'nat') == 'bridge': continue try: subnet = net_spec['gw'] if subnet_lease.is_leasable_subnet(subnet): raise RuntimeError( '%s subnet can only be dynamically allocated' % (subnet, )) except KeyError: subnet = subnet_lease.acquire(self.paths.uuid()) rollback.prependDefer(subnet_lease.release, subnet) net_spec['gw'] = subnet allocated_ips = set([1]) # Check all allocated IPs for nic, dom in nics_by_net[net_name]: if 'ip' not in nic: continue if not _ip_in_subnet(subnet, nic['ip']): raise RuntimeError( "%s:nic%d's IP [%s] is outside the subnet [%s]", dom, dom['nics'].index(nic), nic['ip'], subnet, ) index = int(nic['ip'].split('.'))[3] allocated_ips.add(index) nic['ip'] = _create_ip(subnet, index) # Allocate IPs for domains without assigned IPs for nic, _ in nics_by_net[net_name]: if 'ip' in nic: continue next_vacancy = set(set(range(1, 255)) ^ allocated_ips).pop() allocated_ips.add(next_vacancy) nic['ip'] = _create_ip(subnet, next_vacancy) # Here we will store the domain images: logging.info('Creating bridge...') if 'mapping' not in net_spec: net_spec['mapping'] = {} net_spec['mapping'].update( {dom: nic['ip'] for nic, dom in nics_by_net[net_name]}, ) rollback.clear()