def test_getExternalCloudConnectorModuleName(self): ch = ConfigHolder(config={'foo': 'bar'}, context={'foo': 'bar'}) ch.cloud = 'baz' self.failUnlessRaises(NotFoundError, ccf_module.get_connector_module_name, (ch)) module_name = 'foo.bar.baz' ch = ConfigHolder(config={'cloudconnector': module_name}, context={'foo': 'bar'}) ch.cloud = 'baz' assert module_name == ccf_module.get_connector_module_name(ch)
def do_work(self): ids = self.get_option(self.INSTANCE_IDS_KEY) ch = ConfigHolder(options={ 'verboseLevel': self.options.verbose and 3 or 0, 'retry': False, KEY_RUN_CATEGORY: '' }, context={'foo': 'bar'}) cc = self.get_connector_class()(ch) # pylint: disable=protected-access cc._initialization(self.user_info, **self.get_initialization_extra_kwargs()) fname = self.get_option(self.INSTANCES_IDS_FILE_KEY) if fname: with open(fname) as f: ids += f.read().splitlines() if cc.has_capability(cc.CAPABILITY_VAPP): cc.stop_vapps_by_ids(ids, self.get_option(self.INSTANCES_NAMESPACE)) else: cc._stop_instances_in_namespace( ids, self.get_option(self.INSTANCES_NAMESPACE))
def instantiate_from_cimi(cimi_connector, cimi_cloud_credential): user_info = UserInfo(cimi_connector['instanceName']) cloud_params = { UserInfo.CLOUD_USERNAME_KEY: cimi_cloud_credential['key'], UserInfo.CLOUD_PASSWORD_KEY: cimi_cloud_credential['secret'], 'domain-name': cimi_cloud_credential['domain-name'], 'tenant-name': cimi_cloud_credential['tenant-name'], 'endpoint': cimi_connector.get('endpoint'), 'serviceRegion': cimi_connector.get('serviceRegion'), 'serviceName': cimi_connector.get('serviceName'), 'serviceType': cimi_connector.get('serviceType'), 'identityVersion': cimi_connector.get('identityVersion') } user_info.set_cloud_params(cloud_params) config_holder = ConfigHolder(options={'verboseLevel': 0, 'retry': False}) os.environ['SLIPSTREAM_CONNECTOR_INSTANCE'] = cimi_connector['instanceName'] connector_instance = OpenStackClientCloud(config_holder) connector_instance._initialization(user_info) return connector_instance
def test_getAvailableCloudConnectorsModuleNames(self): ch = ConfigHolder(config={'foo': 'bar'}, context={'foo': 'bar'}) for module_name in self.get_cloudconnector_modulenames(): setattr(ch, CONFIGPARAM_CONNECTOR_MODULE_NAME, module_name) try: assert len(ccf_module.get_connector_module_name(ch)) != 0 except NotFoundError: self.fail('Should not have raised NotFoundError')
def setUp(self): os.environ['SLIPSTREAM_CONNECTOR_INSTANCE'] = 'physicalhost' os.environ['SLIPSTREAM_BOOTSTRAP_BIN'] = 'http://example.com/bootstrap' os.environ['SLIPSTREAM_DIID'] = '00000000-0000-0000-0000-000000000000' if not os.path.exists(CONFIG_FILE): raise Exception('Configuration file %s not found.' % CONFIG_FILE) self.ch = ConfigHolder(configFile=CONFIG_FILE, context={'foo': 'bar'}) os.environ['PHYSICALHOST_ORCHESTRATOR_HOST'] = self.ch.config[ 'PHYSICALHOST_ORCHESTRATOR_HOST'] self.client = PhysicalHostClientCloud(self.ch) self.user_info = UserInfo('physicalhost') self.user_info['physicalhost.private.key'] = self.ch.config[ 'physicalhost.private.key'] self.user_info['physicalhost.password'] = self.ch.config[ 'physicalhost.password'] self.user_info['physicalhost.username'] = self.ch.config[ 'physicalhost.username'] hosta = self.ch.config['physicalhost.hosta'] hostb = self.ch.config['physicalhost.hostb'] node_instance_name_a = 'test_node_a' node_instance_name_b = 'test_node_b' self.node_instances = {} self.node_instances[node_instance_name_a] = NodeInstance({ 'name': node_instance_name_a, 'cloudservice': 'physicalhost', 'image.platform': 'Ubuntu', 'image.imageId': hosta, 'image.id': hosta, 'network': 'private', }) self.node_instances[node_instance_name_b] = NodeInstance({ 'name': node_instance_name_b, 'cloudservice': 'physicalhost', 'image.platform': 'Ubuntu', 'image.imageId': hostb, 'image.id': hostb, 'network': 'private', })
def __init__(self, wrapper, config_holder=ConfigHolder()): self.verboseLevel = 0 super(NodeDeploymentExecutor, self).__init__(wrapper, config_holder) self.SCALE_ACTION_TO_TARGET = \ {self.wrapper.SCALE_ACTION_CREATION: 'onvmadd', self.wrapper.SCALE_ACTION_REMOVAL: 'onvmremove'} self._skip_execute_due_to_vertical_scaling = False
def setUp(self): self.ch = ConfigHolder() self.ch.set('serviceurl', endpoint) self.ch.set('verboseLevel', 3) self.client = Client(self.ch) self.client.login(username, password) self.ch.set('endpoint', endpoint) self.ch.set('session', self.client.get_session())
def get_rtp_all(side_effect, no_block=False): ch = ConfigHolder() ch.set('noBlock', no_block) ch.set('timeout', 1) ch.set('verboseLevel', 3) ch.set('endpoint', 'https://foo.bar') Client._getRuntimeParameter = Mock(side_effect=side_effect) client = Client(ch) client.httpClient.getRuntimeParameter = Mock(side_effect=side_effect) return client.get_rtp_all('foo', 'bar')
def doWork(self): ch = ConfigHolder(self.options) client = Client(ch) if self.options.cancel: client.cancel_abort() else: value = truncate_middle(Client.VALUE_LENGTH_LIMIT, self.reason, '\n(truncated)\n') client.setRuntimeParameter(NodeDecorator.ABORT_KEY, value)
def _download_reports(self, api, run_url): if not (self.options.reports_components or self.options.get_reports_all): return components = [] if self.options.reports_components: components = self.options.reports_components ch = ConfigHolder(options=self.options) rg = ReportsGetter(api, ch) rg.get_reports(run_url_to_uuid(run_url), components=components)
def doWork(self): rvalue = ''.join([random.choice(string.ascii_letters + string.digits) for _ in xrange(self.size)]) if self.key is not None: ch = ConfigHolder(self.options) client = Client(ch) client.setRuntimeParameter(self.key, rvalue) print(rvalue)
def _describe_instances(self): ch = ConfigHolder(options={ 'verboseLevel': 0, 'retry': False, KEY_RUN_CATEGORY: '' }, context={'foo': 'bar'}) cc = self.get_connector_class()(ch) cc._initialization(self.user_info, **self.get_initialization_extra_kwargs()) vms = self._list_instances(cc) return cc, vms
def test_do_not_qualify_parameter(self): orch_node_name = NodeDecorator.orchestratorName + '-cloudX' orch_param = orch_node_name + \ NodeDecorator.NODE_PROPERTY_SEPARATOR + \ 'foo' context = {NodeDecorator.NODE_INSTANCE_NAME_KEY: orch_node_name} ch = ConfigHolder(context=context, config={ 'bar': 'baz', 'endpoint': 'https://foo.bar' }) c = Client(ch) assert orch_param == c._qualifyKey(orch_param)
def test_init_session_login_apikey(self): ch = ConfigHolder() ch.context = {} ch.set('verboseLevel', 0) ch.set('cookie_filename', '/dev/null') ch.set('api_key', 'key') ch.set('api_secret', 'secret') client = HttpClient(ch) client.init_session('http://foo.bar') assert client.session is not None assert client.session.login_params assert 'key' in client.session.login_params assert 'secret' in client.session.login_params
def test_init_session_login_internal(self): ch = ConfigHolder() ch.context = {} ch.set('verboseLevel', 0) ch.set('cookie_filename', '/dev/null') ch.set('username', 'foo') ch.set('password', 'bar') client = HttpClient(ch) client.init_session('http://foo.bar') assert client.session is not None assert client.session.login_params assert 'username' in client.session.login_params assert 'password' in client.session.login_params
def setUp(self): self.serviceurl = 'http://example.com' self.config_holder = ConfigHolder( { 'username': base64.b64encode('user'), 'password': base64.b64encode('pass'), 'cookie_filename': '/var/tmp/cookies', 'serviceurl': self.serviceurl, 'node_instance_name': 'instance-name' }, context={'foo': 'bar'}, config={'foo': 'bar'}) os.environ[ENV_CONNECTOR_INSTANCE] = 'Test' BaseWrapper.is_mutable = Mock(return_value=False)
def _run_instance(self, node_instance): nodename = node_instance.get_name() cloud_connector_class = self.get_connector_class() cloud_connector_class._publish_vm_info = publish_vm_info verbose_level = self.get_option('verbose') and 3 or 0 ch = ConfigHolder(options={ 'verboseLevel': verbose_level, 'retry': False, KEY_RUN_CATEGORY: RUN_CATEGORY_DEPLOYMENT }, context={'foo': 'bar'}, config={'foo': 'bar'}) cc = cloud_connector_class(ch) cc.start_nodes_and_clients(self.user_info, {nodename: node_instance}, self.get_initialization_extra_kwargs())
def __init__(self, wrapper, config_holder=ConfigHolder()): """ :param wrapper: SlipStream client and cloud client wrapper :type wrapper: slipstream.wrappers.CloudWrapper :param config_holder: configuration holder :type config_holder: slipstream.ConfigHolder """ self.wrapper = wrapper self.timeout = 55 * 60 # 55 minutes self.ssLogDir = util.get_platform_reports_dir() self.verboseLevel = 0 config_holder.assign(self) self.reportFilesAndDirsList = [self.ssLogDir] self.node_instance = self._retrieve_my_node_instance() self.recovery_mode = False self._send_reports = False
def test_constructor(self): ch = ConfigHolder() ch.context = {} ch.options = {} ch.config = {} Client(ch) ch.context = {} ch.options = {} ch.config = {'endpoint': 'foo/bar'} c = Client(ch) assert c.ch.endpoint == c.ch.serviceurl == 'foo/bar' ch.context = {} ch.options = {} ch.config = {'serviceurl': 'bar/baz'} c = Client(ch) assert c.ch.serviceurl == 'bar/baz' assert not hasattr(c.ch, 'endpoint')
def test_post_with_data(self): ch = ConfigHolder() ch.context = {} ch.set('verboseLevel', 0) ch.set('cookie_filename', '/dev/null') ch.set('api_key', 'key') ch.set('api_secret', 'secret') client = HttpClient(ch) resp = requests.Response() resp.status_code = 200 resp.get = Mock(return_value=None) resp.request = Mock() resp.request.headers = {} requests.sessions.Session.send = Mock(return_value=resp) client.post('http://example.com', 'a=b\nc=d') args, kwargs = requests.sessions.Session.send.call_args self.assertEqual(len(args), 1) req = args[0] self.assertEqual(req.body, 'a=b\nc=d')
def test_init_session_fail_no_creds(self): ch = ConfigHolder() ch.context = {} ch.set('verboseLevel', 0) ch.set('cookie_filename', '/dev/null') client = HttpClient(ch) client.init_session('http://foo.bar') assert client.session is not None assert client.session.login_params == {} resp = Mock(spec=Response) resp.status_code = 403 resp.cookies = None resp.headers = {} client.session._request = Mock(return_value=resp) client.session.cimi_login = Mock(return_value=resp) try: client.get('http://foo.bar', retry=False) except Exception as ex: assert ex.code == 403 assert client.session.cimi_login.called is True
def doWork(self): ch = ConfigHolder(self.options, context={'empty': None}, config={'empty': None}) client = Client(ch) client.login(self.username, self.password)
def _init_client(self): self.configHolder = ConfigHolder(self.options) self.configHolder.set('serviceurl', self.options.endpoint) self.ss_client = SlipStreamHttpClient(self.configHolder)
def doWork(self): ch = ConfigHolder(self.options) client = Client(ch) client.cancel_abort()
def do_work(self): ch = ConfigHolder(options={ 'verboseLevel': 0, 'retry': False, KEY_RUN_CATEGORY: '' }, context={'foo': 'bar'}) self.cc = self.get_connector_class()(ch) self.cc._initialization(self.user_info, **self.get_initialization_extra_kwargs()) self.base_currency = self.get_option(self.BASE_CURRENCY_KEY) verbose = self.get_option('verbose') dry_run = self.get_option(self.DRY_RUN_KEY) ss_endpoint = self.get_option(self.SS_ENDPOINT_KEY) ss_username = self.get_option(self.SS_USERNAME_KEY) ss_password = self.get_option(self.SS_PASSWORD_KEY) connector_instance_name = self.get_option(self.CONNECTOR_NAME_KEY) filter_connector_vm = ' and '.join([ 'connector/href="{0}"'.format(connector_instance_name), 'resource:type="VM"' ]) self.ssapi = Api(endpoint=ss_endpoint, cookie_file=None, insecure=True) if not dry_run: self.ssapi.login_internal(ss_username, ss_password) self._initialize() service_offers = self._generate_service_offers(connector_instance_name) if not service_offers: raise RuntimeError("No service offer found") if not dry_run and service_offers: self._add_service_attribute_namespace_if_not_exist('resource') self._add_service_attribute_namespace_if_not_exist('price') prefix = self._get_prefix() if prefix: self._add_service_attribute_namespace_if_not_exist(prefix) service_offers_ids = set() for service_offer in service_offers: if dry_run: print('\nService offer {0}:\n{1}'.format( service_offer['name'], service_offer)) else: cimi_filter = \ ' and '.join([filter_connector_vm, 'resource:class="{0}"'.format(service_offer['resource:class']), 'resource:vcpu={0}'.format(service_offer['resource:vcpu']), 'resource:ram={0}'.format(service_offer['resource:ram']), 'resource:disk={0}'.format(service_offer['resource:disk']), 'resource:operatingSystem="{0}"'.format(service_offer['resource:operatingSystem']), 'resource:country="{0}"'.format(service_offer['resource:country']), 'resource:instanceType="{0}"'.format(service_offer['resource:instanceType'])]) search_result = self.ssapi.cimi_search('serviceOffers', filter=cimi_filter) result_list = search_result.resources_list result_count = len(result_list) if result_count == 0: if verbose: print( '\nAddinging the following service offer {0} to {1}...\n{2}' .format(service_offer['name'], ss_endpoint, service_offer)) response = self.ssapi.cimi_add('serviceOffers', service_offer) service_offers_ids.add(response.json['resource-id']) elif result_count == 1: if verbose: print( '\nUpdating the following service offer {0} to {1}...\n{2}' .format(service_offer['name'], ss_endpoint, service_offer)) response = self.ssapi.cimi_edit(result_list[0].id, service_offer) service_offers_ids.add(response.id) else: print( '\n!!! Warning duplicates found of following service offer on {0} !!!\n{1}' .format(ss_endpoint, service_offer['name'])) for result in result_list: service_offers_ids.add(result.id) if not dry_run: response = self.ssapi.cimi_search('serviceOffers', filter=filter_connector_vm) old_service_offers_ids = set(r.id for r in response.resources()) service_offers_ids_to_delete = old_service_offers_ids - service_offers_ids for id in service_offers_ids_to_delete: if verbose: offer = self.ssapi.cimi_get(id) print( '\nDeleting the following service offer with id {0}...\n{1}' .format(id, offer.json)) self.ssapi.cimi_delete(id) print('\n\nCongratulation, executon completed.')
def setUp(self): cn = getConnectorClass().cloudName os.environ['SLIPSTREAM_CONNECTOR_INSTANCE'] = cn os.environ['SLIPSTREAM_BOOTSTRAP_BIN'] = 'http://example.com/bootstrap' os.environ['SLIPSTREAM_DIID'] = \ '%s-1234-1234-1234-123456789012' % str(int(time.time()))[2:] if not os.path.exists(CONFIG_FILE): raise Exception('Configuration file %s not found.' % CONFIG_FILE) self.ch = ConfigHolder(configFile=CONFIG_FILE, context={'foo': 'bar'}) self.ch.verboseLevel = int(self.ch.verboseLevel) self.user_info = UserInfo(cn) self.user_info['General.ssh.public.key'] = self.ch.config[ 'General.ssh.public.key'] self.user_info[cn + '.user.uuid'] = self.ch.config[cn + '.user.uuid'] self.user_info[cn + '.username'] = self.ch.config[cn + '.username'] self.user_info[cn + '.password'] = self.ch.config[cn + '.password'] self.user_info[cn + '.endpoint'] = self.ch.config[cn + '.endpoint'] node_name = 'test_node' self.multiplicity = int(self.ch.config['multiplicity']) self.node_instances = {} for i in range(1, self.multiplicity + 1): node_instance_name = node_name + '.' + str(i) self.node_instances[node_instance_name] = NodeInstance({ NodeDecorator.NODE_NAME_KEY: node_name, NodeDecorator.NODE_INSTANCE_NAME_KEY: node_instance_name, 'cloudservice': cn, 'image.description': 'This is a test image.', 'image.platform': self.ch.config[cn + '.image.platform'], 'image.id': self.ch.config[cn + '.imageid'], cn + '.ram': self.ch.config[cn + '.ram'], cn + '.cpu': self.ch.config[cn + '.cpu'], 'network': self.ch.config['network'] }) self.node_instance = NodeInstance({ NodeDecorator.NODE_NAME_KEY: NodeDecorator.MACHINE_NAME, NodeDecorator.NODE_INSTANCE_NAME_KEY: NodeDecorator.MACHINE_NAME, 'cloudservice': cn, 'image.description': 'This is a test image.', 'image.platform': self.ch.config[cn + '.image.platform'], 'image.loginUser': self.ch.config[cn + '.image.loginuser'], 'image.id': self.ch.config[cn + '.imageid'], cn + '.ram': self.ch.config[cn + '.ram'], cn + '.cpu': self.ch.config[cn + '.cpu'], 'network': self.ch.config['network'], 'image.prerecipe': """#!/bin/sh set -e set -x ls -l /tmp dpkg -l | egrep "nano|lvm" || true """, 'image.packages': ['lvm2', 'nano'], 'image.recipe': """#!/bin/sh set -e set -x dpkg -l | egrep "nano|lvm" || true lvs """ })
def setUp(self): os.environ['SLIPSTREAM_CONNECTOR_INSTANCE'] = 'Test' self.ch = ConfigHolder(config={'foo': 'bar'}, context={'foo': 'bar'}) self.ch.set(KEY_RUN_CATEGORY, RUN_CATEGORY_DEPLOYMENT)
def setUp(self): os.environ[ 'SLIPSTREAM_CONNECTOR_INSTANCE'] = self.connector_instance_name os.environ['SLIPSTREAM_BOOTSTRAP_BIN'] = 'http://example.com/bootstrap' os.environ['SLIPSTREAM_DIID'] = '00000000-0000-0000-0000-000000000000' if not os.path.exists(CONFIG_FILE): raise Exception('Configuration file %s not found.' % CONFIG_FILE) self.ch = ConfigHolder(configFile=CONFIG_FILE, context={'foo': 'bar'}) self.ch.set(KEY_RUN_CATEGORY, '') OpenNebulaClientCloud._publish_vm_info = publish_vm_info # pylint: disable=protected-access self.client = OpenNebulaClientCloud(self.ch) self.user_info = UserInfo(self.connector_instance_name) self.user_info[ 'General.' + UserInfo.SSH_PUBKEY_KEY] = self.ch.config['General.ssh.public.key'] self.user_info[self.constructKey( 'endpoint')] = self.ch.config['opennebula.endpoint'] self.user_info[self.constructKey( 'username')] = self.ch.config['opennebula.username'] self.user_info[self.constructKey( 'password')] = self.ch.config['opennebula.password'] self.user_info[self.constructKey( UserInfo.NETWORK_PUBLIC_KEY )] = self.ch.config['opennebula.networkPublic'] self.user_info[self.constructKey( UserInfo.NETWORK_PRIVATE_KEY )] = self.ch.config['opennebula.networkPrivate'] self.user_info[self.constructKey('cpuRatio')] = '1.0' image_id = self.ch.config['opennebula.imageid'] instance_type = self.ch.config.get('opennebula.intance.type', 'm1.tiny') node_name = 'test_node' self.multiplicity = 1 self.node_instances = {} for i in range(1, self.multiplicity + 1): node_instance_name = node_name + '.' + str(i) self.node_instances[node_instance_name] = NodeInstance({ NodeDecorator.NODE_NAME_KEY: node_name, NodeDecorator.NODE_INSTANCE_NAME_KEY: node_instance_name, 'cloudservice': self.connector_instance_name, 'image.platform': 'Ubuntu', 'image.imageId': image_id, 'image.id': image_id, 'network': self.ch.config['opennebula.network'], self.constructKey('instance.type'): instance_type, self.constructKey('ram'): '2', self.constructKey('cpu'): '1' }) self.node_instance = NodeInstance({ NodeDecorator.NODE_NAME_KEY: NodeDecorator.MACHINE_NAME, NodeDecorator.NODE_INSTANCE_NAME_KEY: NodeDecorator.MACHINE_NAME, 'cloudservice': self.connector_instance_name, 'image.platform': 'Ubuntu', 'image.imageId': image_id, 'image.id': image_id, self.constructKey('instance.type'): instance_type, 'image.prerecipe': """#!/bin/sh set -e set -x ls -l /tmp dpkg -l | egrep "nano|lvm" || true """, 'image.packages': ['lvm2', 'nano'], 'image.recipe': """#!/bin/sh set -e set -x dpkg -l | egrep "nano|lvm" || true lvs """ })
def doWork(self): ch = ConfigHolder(self.options) client = Client(ch) client.terminateRun()
def setUp(self): cloudName = TestOkeanosClientCloud.CLOUD_NAME flavorKey = TestOkeanosClientCloud.FLAVOR_KEY resizeFlavorKey = TestOkeanosClientCloud.RESIZE_FLAVOR_KEY os.environ['SLIPSTREAM_CONNECTOR_INSTANCE'] = cloudName os.environ['SLIPSTREAM_BOOTSTRAP_BIN'] = 'http://example.com/bootstrap' os.environ['SLIPSTREAM_DIID'] = \ '%s-1234-1234-1234-123456789012' % str(int(time.time()))[2:] if not os.path.exists(CONFIG_FILE): raise Exception('Configuration file %s not found.' % CONFIG_FILE) self.ch = ConfigHolder(configFile=CONFIG_FILE, context={'foo': 'bar'}) self.ch.verboseLevel = int(self.ch.verboseLevel) flavor = self.ch.config[flavorKey] resizeFlavor = self.ch.config[resizeFlavorKey] self.log("Initial Flavor: '%s' = %s" % (flavorKey, flavor)) self.log("Resize Flavor: '%s' = %s" % (resizeFlavorKey, resizeFlavor)) self.user_info = UserInfo(cloudName) self.user_info['General.ssh.public.key'] = self.ch.config['General.ssh.public.key'] self.user_info[cloudName + '.endpoint'] = self.ch.config[cloudName + '.auth_url'] self.user_info[cloudName + '.username'] = self.ch.config[cloudName + '.user.uuid'] self.user_info[cloudName + '.password'] = self.ch.config[cloudName + '.token'] self.user_info[cloudName + '.project.id'] = self.ch.config[cloudName + '.project.id'] node_name = 'test_node' self.multiplicity = int(self.ch.config['multiplicity']) self.node_instances = {} for i in range(1, self.multiplicity + 1): node_instance_name = node_name + '.' + str(i) ni = NodeInstance({ NodeDecorator.NODE_NAME_KEY: node_name, NodeDecorator.NODE_INSTANCE_NAME_KEY: node_instance_name, 'cloudservice': cloudName, 'image.description': 'This is a test image.', 'image.platform': self.ch.config[cloudName + '.image.platform'], 'image.id': self.ch.config[cloudName + '.imageid'], flavorKey: flavor, resizeFlavorKey: resizeFlavor, 'network': self.ch.config['network'] }) ni.set_parameter(NodeDecorator.SCALE_DISK_ATTACH_SIZE, 1) self.node_instances[node_instance_name] = ni self.node_instance = NodeInstance({ NodeDecorator.NODE_NAME_KEY: node_name, NodeDecorator.NODE_INSTANCE_NAME_KEY: NodeDecorator.MACHINE_NAME, 'cloudservice': cloudName, 'disk.attach.size': self.ch.config[cloudName + '.disk.attach.size'], 'image.description': 'This is a test image.', 'image.platform': self.ch.config[cloudName + '.image.platform'], 'image.loginUser': self.ch.config[cloudName + '.image.loginuser'], 'image.id': self.ch.config[cloudName + '.imageid'], flavorKey: flavor, resizeFlavorKey: resizeFlavor, 'network': self.ch.config['network'], 'image.prerecipe': """#!/bin/sh set -e set -x ls -l /tmp dpkg -l | egrep "nano|lvm" || true """, 'image.packages': ['lvm2', 'nano'], 'image.recipe': """#!/bin/sh set -e set -x dpkg -l | egrep "nano|lvm" || true lvs """ })