def _s3_decrypt_image(context, encrypted_filename, encrypted_key, encrypted_iv, decrypted_filename): encrypted_key = binascii.a2b_hex(encrypted_key) encrypted_iv = binascii.a2b_hex(encrypted_iv) cert_client = clients.nova_cert(context) try: key = cert_client.decrypt_text(base64.b64encode(encrypted_key)) except Exception as exc: msg = _('Failed to decrypt private key: %s') % exc raise exception.EC2Exception(msg) try: iv = cert_client.decrypt_text(base64.b64encode(encrypted_iv)) except Exception as exc: msg = _('Failed to decrypt initialization vector: %s') % exc raise exception.EC2Exception(msg) try: processutils.execute('openssl', 'enc', '-d', '-aes-128-cbc', '-in', '%s' % (encrypted_filename, ), '-K', '%s' % (key, ), '-iv', '%s' % (iv, ), '-out', '%s' % (decrypted_filename, )) except processutils.ProcessExecutionError as exc: raise exception.EC2Exception( _('Failed to decrypt image file ' '%(image_file)s: %(err)s') % { 'image_file': encrypted_filename, 'err': exc.stdout })
def _decrypt_text(text): private_key_file = CONF.x509_root_private_key if not private_key_file: msg = _("Path to ca private key isn't configured") raise exception.EC2Exception(msg) with open(private_key_file, 'rb') as f: data = f.read() priv_key = serialization.load_pem_private_key(data, None, backends.default_backend()) return priv_key.decrypt(text, padding.PKCS1v15())
def db_sync(version=None): if version is not None: try: version = int(version) except ValueError: raise exception.EC2Exception(_("version should be an integer")) current_version = db_version() repository = _find_migrate_repo() if version is None or version > current_version: return versioning_api.upgrade(get_engine(), repository, version) else: return versioning_api.downgrade(get_engine(), repository, version)
def db_version(): repository = _find_migrate_repo() try: return versioning_api.db_version(get_engine(), repository) except versioning_exceptions.DatabaseNotControlledError: meta = sqlalchemy.MetaData() engine = get_engine() meta.reflect(bind=engine) tables = meta.tables if len(tables) == 0: db_version_control(INIT_VERSION) return versioning_api.db_version(get_engine(), repository) else: # Some pre-Essex DB's may not be version controlled. # Require them to upgrade using Essex first. raise exception.EC2Exception( _("Upgrade DB using Essex release first."))
def test_execute_error(self): @tools.screen_all_logs def do_check(ex, status, code, message): self.controller.reset_mock() self.controller.fake_action.side_effect = ex res = self.request.send(self.application) self.assertEqual(status, res.status_code) self.assertEqual('text/xml', res.content_type) expected_xml = fakes.XML_ERROR_TEMPLATE % { 'code': code, 'message': message, 'request_id': self.fake_context.request_id } self.assertThat(res.body.decode("utf-8"), matchers.XMLMatches(expected_xml)) self.controller.fake_action.assert_called_once_with( self.fake_context, param='fake_param') do_check(exception.EC2Exception('fake_msg'), 400, 'EC2Exception', 'fake_msg') do_check(KeyError('fake_msg'), 500, 'KeyError', 'Unknown error occurred.') do_check(exception.InvalidVpcIDNotFound('fake_msg'), 400, 'InvalidVpcID.NotFound', 'fake_msg') do_check(nova_exception.BadRequest(400, message='fake_msg'), 400, 'BadRequest', 'fake_msg') do_check(glance_exception.HTTPBadRequest(), 400, 'HTTPBadRequest', 'HTTP HTTPBadRequest') do_check(cinder_exception.BadRequest(400, message='fake_msg'), 400, 'BadRequest', 'fake_msg') do_check(neutron_exception.BadRequest(message='fake_msg'), 400, 'BadRequest', 'fake_msg') do_check(keystone_exception.BadRequest(message='fake_msg'), 400, 'BadRequest', 'fake_msg (HTTP 400)') do_check( botocore_exceptions.ClientError( { 'Error': { 'Code': '', 'Message': '' }, 'Code': 'FakeCode', 'Message': 'fake_msg' }, 'register_image'), 400, 'FakeCode', 'fake_msg')
def delayed_create(context, image, name, os_instance): try: os_instance.stop() # wait instance for really stopped start_time = time.time() while os_instance.status != 'SHUTOFF': time.sleep(1) os_instance.get() # NOTE(yamahata): timeout and error. 1 hour for now for safety. # Is it too short/long? # Or is there any better way? timeout = 1 * 60 * 60 if time.time() > start_time + timeout: err = (_("Couldn't stop instance within %d sec") % timeout) raise exception.EC2Exception(message=err) # NOTE(ft): create an image with ec2_id metadata to let other code # link os and db objects in race conditions os_image_id = os_instance.create_image( name, metadata={'ec2_id': image['id']}) image['os_id'] = os_image_id db_api.update_item(context, image) except Exception: LOG.exception(_LE('Failed to complete image %s creation'), image.id) try: image['state'] = 'failed' db_api.update_item(context, image) except Exception: LOG.warning(_LW("Couldn't set 'failed' state for db image %s"), image.id, exc_info=True) try: os_instance.start() except Exception: LOG.warning(_LW('Failed to start instance %(i_id)s after ' 'completed creation of image %(image_id)s'), { 'i_id': instance['id'], 'image_id': image['id'] }, exc_info=True)
def __get_backend(self): if not self.__backend: if self.__config_group is None: backend_name = CONF[self.__pivot] else: backend_name = CONF[self.__config_group][self.__pivot] if backend_name not in self.__backends: msg = _('Invalid backend: %s') % backend_name raise exception.EC2Exception(msg) backend = self.__backends[backend_name] if isinstance(backend, tuple): name = backend[0] fromlist = backend[1] else: name = backend fromlist = backend self.__backend = __import__(name, None, None, fromlist) return self.__backend
def create_image(context, instance_id, name=None, description=None, no_reboot=False, block_device_mapping=None): instance = ec2utils.get_db_item(context, instance_id) if not instance_api._is_ebs_instance(context, instance['os_id']): msg = _('Instance does not have a volume attached at root (null).') raise exception.InvalidParameterValue(value=instance_id, parameter='InstanceId', reason=msg) nova = clients.nova(context) os_instance = nova.servers.get(instance['os_id']) restart_instance = False if not no_reboot and os_instance.status != 'SHUTOFF': if os_instance.status != 'ACTIVE': # TODO(ft): Change the error code and message with the real AWS # ones msg = _('Instance must be run or stopped') raise exception.IncorrectState(reason=msg) restart_instance = True os_instance.stop() # wait instance for really stopped start_time = time.time() while os_instance.status != 'SHUTOFF': time.sleep(1) os_instance.get() # NOTE(yamahata): timeout and error. 1 hour for now for safety. # Is it too short/long? # Or is there any better way? timeout = 1 * 60 * 60 if time.time() > start_time + timeout: err = _("Couldn't stop instance within %d sec") % timeout raise exception.EC2Exception(message=err) # meaningful image name name_map = dict(instance=instance['os_id'], now=timeutils.isotime()) name = name or _('image of %(instance)s at %(now)s') % name_map glance = clients.glance(context) with common.OnCrashCleaner() as cleaner: os_image_id = os_instance.create_image(name) cleaner.addCleanup(glance.images.delete, os_image_id) # TODO(andrey-mp): snapshot and volume also must be deleted in case # of error os_image = glance.images.get(os_image_id) image = db_api.add_item(context, _get_os_image_kind(os_image), { 'os_id': os_image_id, 'is_public': False, 'description': description }) if restart_instance: os_instance.start() return {'imageId': image['id']}