コード例 #1
0
    def __init__(self, middleware, method_name, serviceobj, method, args, options, pipes):
        self._finished = asyncio.Event()
        self.middleware = middleware
        self.method_name = method_name
        self.serviceobj = serviceobj
        self.method = method
        self.args = args
        self.options = options
        self.pipes = pipes or Pipes(input=None, output=None)

        self.id = None
        self.lock = None
        self.result = None
        self.error = None
        self.exception = None
        self.exc_info = None
        self.state = State.WAITING
        self.progress = {
            'percent': None,
            'description': None,
            'extra': None,
        }
        self.time_started = datetime.now()
        self.time_finished = None
        self.loop = asyncio.get_event_loop()
        self.future = None

        self.logs_path = None
        self.logs_fd = None
        self.logs_excerpt = None

        if self.options["check_pipes"]:
            for pipe in self.options["pipes"]:
                self.check_pipe(pipe)
コード例 #2
0
ファイル: webui.py プロジェクト: PersonalBSD/freenas-core
    async def do_create(self, job, options):
        """
        Create a new database entry with identifier as the tag, all entries are
        lowercased

        Then puts the file in the /var/db/system/webui/images directory
        """
        identifier = options.get('identifier')
        self.__ensure_dir()

        try:
            id = await self.middleware.call('datastore.insert',
                                            'system.filesystem',
                                            {'identifier': identifier.lower()})
        except IntegrityError as e:
            # Likely a duplicate entry
            raise CallError(e)

        final_location = f"/var/db/system/webui/images/{id}.png"
        put_job = await self.middleware.call(
            'filesystem.put',
            final_location, {"mode": 0o755},
            pipes=Pipes(input=job.pipes.input))
        await put_job.wait()

        return id
コード例 #3
0
ファイル: service.py プロジェクト: MrYHM/freenas
    async def download(self, method, args, filename):
        """
        Core helper to call a job marked for download.

        Returns the job id and the URL for download.
        """
        job = await self.middleware.call(method, *args, pipes=Pipes(output=self.middleware.pipe()))
        token = await self.middleware.call('auth.generate_token', 300, {'filename': filename, 'job': job.id})
        self.middleware.fileapp.register_job(job.id)
        return job.id, f'/_download/{job.id}?auth_token={token}'
コード例 #4
0
ファイル: job.py プロジェクト: patelneel4/freenas
    def __init__(self, middleware, method_name, serviceobj, method, args,
                 options, pipes, on_progress_cb):
        self._finished = asyncio.Event(loop=middleware.loop)
        self.middleware = middleware
        self.method_name = method_name
        self.serviceobj = serviceobj
        self.method = method
        self.args = args
        self.options = options
        self.pipes = pipes or Pipes(input=None, output=None)
        self.on_progress_cb = on_progress_cb

        self.id = None
        self.lock = None
        self.result = None
        self.error = None
        self.exception = None
        self.exc_info = None
        self.aborted = False
        self.state = State.WAITING
        self.description = None
        self.progress = {
            'percent': None,
            'description': None,
            'extra': None,
        }
        self.internal_data = {}
        self.time_started = datetime.utcnow()
        self.time_finished = None
        self.loop = self.middleware.loop
        self.future = None

        self.logs_path = None
        self.logs_fd = None
        self.logs_excerpt = None

        if self.options["check_pipes"]:
            for pipe in self.options["pipes"]:
                self.check_pipe(pipe)

        if self.options["description"]:
            try:
                self.description = self.options["description"](*args)
            except Exception:
                logger.error("Error setting job description", exc_info=True)
コード例 #5
0
ファイル: support.py プロジェクト: zeroyou/freenas
    async def new_ticket(self, job, data):
        """
        Creates a new ticket for support.
        This is done using the support proxy API.
        For FreeNAS it will be created on Redmine and for TrueNAS on SupportSuite.

        For FreeNAS `criticality`, `environment`, `phone`, `name` and `email` attributes are not required.
        For TrueNAS `username`, `password` and `type` attributes are not required.
        """

        await self.middleware.call('network.general.will_perform_activity', 'support')

        job.set_progress(1, 'Gathering data')

        sw_name = 'freenas' if not await self.middleware.call('system.is_enterprise') else 'truenas'

        if sw_name == 'freenas':
            required_attrs = ('type', 'username', 'password')
        else:
            required_attrs = ('phone', 'name', 'email', 'criticality', 'environment')
            data['serial'] = (await self.middleware.call('system.dmidecode_info'))['system-serial-number']
            license = (await self.middleware.call('system.info'))['license']
            if license:
                data['company'] = license['customer_name']
            else:
                data['company'] = 'Unknown'

        for i in required_attrs:
            if i not in data:
                raise CallError(f'{i} is required', errno.EINVAL)

        data['version'] = (await self.middleware.call('system.version')).split('-', 1)[-1]
        if 'username' in data:
            data['user'] = data.pop('username')
        debug = data.pop('attach_debug')

        type_ = data.get('type')
        if type_:
            data['type'] = type_.lower()

        job.set_progress(20, 'Submitting ticket')

        try:
            r = await self.middleware.run_in_thread(lambda: requests.post(
                f'https://{ADDRESS}/{sw_name}/api/v1.0/ticket',
                data=json.dumps(data),
                headers={'Content-Type': 'application/json'},
                timeout=10,
            ))
            result = r.json()
        except simplejson.JSONDecodeError:
            self.logger.debug(f'Failed to decode ticket attachment response: {r.text}')
            raise CallError('Invalid proxy server response', errno.EBADMSG)
        except requests.ConnectionError as e:
            raise CallError(f'Connection error {e}', errno.EBADF)
        except requests.Timeout:
            raise CallError('Connection time out', errno.ETIMEDOUT)

        if r.status_code != 200:
            self.logger.debug(f'Support Ticket failed ({r.status_code}): {r.text}', r.status_code, r.text)
            raise CallError('Ticket creation failed, try again later.', errno.EINVAL)

        if result['error']:
            raise CallError(result['message'], errno.EINVAL)

        ticket = result.get('ticketnum')
        url = result.get('message')
        if not ticket:
            raise CallError('New ticket number was not informed', errno.EINVAL)
        job.set_progress(50, f'Ticket created: {ticket}', extra={'ticket': ticket})

        if debug:
            job.set_progress(60, 'Generating debug file')

            debug_job = await self.middleware.call(
                'system.debug', pipes=Pipes(output=self.middleware.pipe()),
            )

            if await self.middleware.call('system.is_enterprise') and await self.middleware.call('failover.licensed'):
                debug_name = 'debug-{}.tar'.format(time.strftime('%Y%m%d%H%M%S'))
            else:
                debug_name = 'debug-{}-{}.txz'.format(
                    socket.gethostname().split('.')[0],
                    time.strftime('%Y%m%d%H%M%S'),
                )

            job.set_progress(80, 'Attaching debug file')

            t = {
                'ticket': ticket,
                'filename': debug_name,
            }
            if 'user' in data:
                t['username'] = data['user']
            if 'password' in data:
                t['password'] = data['password']
            tjob = await self.middleware.call(
                'support.attach_ticket', t, pipes=Pipes(input=self.middleware.pipe()),
            )

            def copy():
                try:
                    rbytes = 0
                    while True:
                        r = debug_job.pipes.output.r.read(1048576)
                        if r == b'':
                            break
                        rbytes += len(r)
                        if rbytes > 20971520:
                            raise CallError('Debug too large to attach', errno.EFBIG)
                        tjob.pipes.input.w.write(r)
                finally:
                    tjob.pipes.input.w.close()

            await self.middleware.run_in_thread(copy)

            await debug_job.wait()
            await tjob.wait()
        else:
            job.set_progress(100)

        return {
            'ticket': ticket,
            'url': url,
        }
コード例 #6
0
ファイル: support.py プロジェクト: jpaetzel/freenas
    async def new_ticket(self, job, data):
        """
        Creates a new ticket for support.
        This is done using the support proxy API.
        For FreeNAS it will be created on Redmine and for TrueNAS on SupportSuite.

        For FreeNAS `criticality`, `environment`, `phone`, `name` and `email` attributes are not required.
        For TrueNAS `username`, `password` and `type` attributes are not required.
        """

        job.set_progress(1, 'Gathering data')

        sw_name = 'freenas' if await self.middleware.call('system.is_freenas'
                                                          ) else 'truenas'

        if sw_name == 'freenas':
            required_attrs = ('type', 'username', 'password')
        else:
            required_attrs = ('phone', 'name', 'email', 'criticality',
                              'environment')
            data['serial'] = (await (await Popen(
                ['/usr/local/sbin/dmidecode', '-s', 'system-serial-number'],
                stdout=subprocess.PIPE)).communicate()
                              )[0].decode().split('\n')[0].upper()
            license = get_license()[0]
            if license:
                data['company'] = license.customer_name
            else:
                data['company'] = 'Unknown'

        for i in required_attrs:
            if i not in data:
                raise CallError(f'{i} is required', errno.EINVAL)

        data['version'] = (await self.middleware.call('system.version')).split(
            '-', 1)[-1]
        if 'username' in data:
            data['user'] = data.pop('username')
        debug = data.pop('attach_debug')

        type_ = data.get('type')
        if type_:
            data['type'] = type_.lower()

        job.set_progress(20, 'Submitting ticket')

        try:
            r = await self.middleware.run_in_thread(lambda: requests.post(
                f'https://{ADDRESS}/{sw_name}/api/v1.0/ticket',
                data=json.dumps(data),
                headers={'Content-Type': 'application/json'},
                timeout=10,
            ))
            result = r.json()
        except simplejson.JSONDecodeError:
            self.logger.debug(
                f'Failed to decode ticket attachment response: {r.text}')
            raise CallError('Invalid proxy server response', errno.EBADMSG)
        except requests.ConnectionError as e:
            raise CallError(f'Connection error {e}', errno.EBADF)
        except requests.Timeout:
            raise CallError('Connection time out', errno.ETIMEDOUT)

        if r.status_code != 200:
            self.logger.debug(
                f'Support Ticket failed ({r.status_code}): {r.text}',
                r.status_code, r.text)
            raise CallError('Ticket creation failed, try again later.',
                            errno.EINVAL)

        if result['error']:
            raise CallError(result['message'], errno.EINVAL)

        ticket = result.get('ticketnum')
        url = result.get('message')
        if not ticket:
            raise CallError('New ticket number was not informed', errno.EINVAL)
        job.set_progress(50,
                         f'Ticket created: {ticket}',
                         extra={'ticket': ticket})

        if debug:
            # FIXME: generate debug from middleware
            mntpt, direc, dump = await self.middleware.run_in_thread(
                debug_get_settings)

            job.set_progress(60, 'Generating debug file')
            await self.middleware.run_in_thread(debug_generate)

            not_freenas = not (await self.middleware.call('system.is_freenas'))
            if not_freenas:
                not_freenas &= await self.middleware.call(
                    'notifier.failover_licensed')
            if not_freenas:
                debug_file = f'{direc}/debug.tar'
                debug_name = 'debug-{}.tar'.format(
                    time.strftime('%Y%m%d%H%M%S'))
            else:
                debug_file = dump
                debug_name = 'debug-{}-{}.txz'.format(
                    socket.gethostname().split('.')[0],
                    time.strftime('%Y%m%d%H%M%S'),
                )

            job.set_progress(80, 'Attaching debug file')

            t = {
                'ticket': ticket,
                'filename': debug_name,
            }
            if 'user' in data:
                t['username'] = data['user']
            if 'password' in data:
                t['password'] = data['password']
            tjob = await self.middleware.call(
                'support.attach_ticket',
                t,
                pipes=Pipes(input=self.middleware.pipe()))

            with open(debug_file, 'rb') as f:
                await self.middleware.run_in_io_thread(shutil.copyfileobj, f,
                                                       tjob.pipes.input.w)
                await self.middleware.run_in_io_thread(tjob.pipes.input.w.close
                                                       )

            await tjob.wait()
        else:
            job.set_progress(100)

        return {
            'ticket': ticket,
            'url': url,
        }
コード例 #7
0
    async def new_ticket(self, job, data):
        """
        Creates a new ticket for support.
        This is done using the support proxy API.
        For TrueNAS SCALE it will be created on JIRA and for TrueNAS SCALE Enterprise on Salesforce.

        For SCALE `criticality`, `environment`, `phone`, `name` and `email` attributes are not required.
        For SCALE Enterprise `token` and `type` attributes are not required.
        """

        await self.middleware.call('network.general.will_perform_activity', 'support')

        job.set_progress(1, 'Gathering data')

        sw_name = 'freenas' if not await self.middleware.call('system.is_enterprise') else 'truenas'

        if sw_name == 'freenas':
            required_attrs = ('type', 'token')
        else:
            required_attrs = ('phone', 'name', 'email', 'criticality', 'environment')
            data['serial'] = (await self.middleware.call('system.dmidecode_info'))['system-serial-number']
            license = await self.middleware.call('system.license')
            if license:
                data['company'] = license['customer_name']
            else:
                data['company'] = 'Unknown'

        for i in required_attrs:
            if i not in data:
                raise CallError(f'{i} is required', errno.EINVAL)

        data['version'] = (await self.middleware.call('system.version')).split('-', 1)[-1]
        debug = data.pop('attach_debug')

        type_ = data.get('type')
        if type_:
            data['type'] = type_.lower()

        job.set_progress(20, 'Submitting ticket')

        result = await post(
            f'https://{ADDRESS}/{sw_name}/api/v1.0/ticket',
            data=json.dumps(data),
        )
        if result['error']:
            raise CallError(result['message'], errno.EINVAL)

        ticket = result.get('ticketnum')
        url = result.get('message')
        if not ticket:
            raise CallError('New ticket number was not informed', errno.EINVAL)
        job.set_progress(50, f'Ticket created: {ticket}', extra={'ticket': ticket})

        has_debug = False
        if debug:
            job.set_progress(60, 'Generating debug file')

            debug_job = await self.middleware.call(
                'system.debug', pipes=Pipes(output=self.middleware.pipe()),
            )

            if await self.middleware.call('failover.licensed'):
                debug_name = 'debug-{}.tar'.format(time.strftime('%Y%m%d%H%M%S'))
            else:
                debug_name = 'debug-{}-{}.txz'.format(
                    (await self.middleware.call('system.hostname')).split('.')[0],
                    time.strftime('%Y%m%d%H%M%S'),
                )

            with tempfile.NamedTemporaryFile("w+b") as f:
                def copy1():
                    nonlocal has_debug
                    try:
                        rbytes = 0
                        while True:
                            r = debug_job.pipes.output.r.read(1048576)
                            if r == b'':
                                break

                            rbytes += len(r)
                            if rbytes > DEBUG_MAX_SIZE * 1048576:
                                return

                            f.write(r)

                        f.seek(0)
                        has_debug = True
                    finally:
                        debug_job.pipes.output.r.read()

                await self.middleware.run_in_thread(copy1)
                await debug_job.wait()

                if has_debug:
                    job.set_progress(80, 'Attaching debug file')

                    t = {
                        'ticket': ticket,
                        'filename': debug_name,
                    }
                    if 'token' in data:
                        t['token'] = data['token']
                    tjob = await self.middleware.call(
                        'support.attach_ticket', t, pipes=Pipes(input=self.middleware.pipe()),
                    )

                    def copy2():
                        try:
                            shutil.copyfileobj(f, tjob.pipes.input.w)
                        finally:
                            tjob.pipes.input.w.close()

                    await self.middleware.run_in_thread(copy2)
                    await tjob.wait()
        else:
            job.set_progress(100)

        return {
            'ticket': ticket,
            'url': url,
            'has_debug': has_debug,
        }