예제 #1
0
    def check_train(self, train):
        handler = CheckUpdateHandler()
        manifest = CheckForUpdates(
            diff_handler=handler.diff_call,
            handler=handler.call,
            train=train,
        )

        if not manifest:
            return {'status': 'UNAVAILABLE'}

        data = {
            'status': 'AVAILABLE',
            'changes': handler.changes,
            'notice': manifest.Notice(),
            'notes': manifest.Notes(),
        }

        conf = Configuration.Configuration()
        sys_mani = conf.SystemManifest()
        if sys_mani:
            sequence = sys_mani.Sequence()
        else:
            sequence = ''
        data['changelog'] = get_changelog(train,
                                          start=sequence,
                                          end=manifest.Sequence())

        data['version'] = manifest.Version()
        return data
예제 #2
0
    def get_trains_data(self):
        try:
            redir_trains = self._get_redir_trains()
        except Exception:
            self.logger.warn('Failed to retrieve trains redirection',
                             exc_info=True)
            redir_trains = {}

        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()

        trains = {}
        for name, descr in (conf.AvailableTrains() or {}).items():
            train = conf._trains.get(name)
            if train is None:
                train = Train.Train(name, descr)

            trains[train.Name()] = {
                'description': descr,
                'sequence': train.LastSequence(),
            }

        return {
            'trains': trains,
            'current_train': conf.CurrentTrain(),
            'trains_redirection': redir_trains,
        }
예제 #3
0
def CheckForUpdates(root = None, handler = None):
    """
    Check for an updated manifest.
    Very simple, uses the configuration module.
    Returns the new manifest if there is an update,
    and None otherwise.
    (It determines if there is an update if the latest-found
    manifest contains differences from the current system
    manifest.)
    The optional argument handler is a function that
    will be called for each difference in the new manifest
    (if there is one); it will be called with three
    arguments:  operation, package, old package.
    operation will be "delete", "upgrade", or "install";
    old package will be None for delete and install.
    """
    conf = Configuration.Configuration(root)
    cur = conf.SystemManifest()
    m = conf.FindLatestManifest()
    log.debug("Current sequence = %s, available sequence = %s" % (cur.Sequence(), m.Sequence()
                                                                             if m is not None else "None"))
    if m is None:
        raise ValueError("Manifest could not be found!")
    diffs = Manifest.CompareManifests(cur, m)
    update = False
    for (pkg, op,old) in diffs:
        update = True
        if handler is not None:
            handler(op, pkg, old)
    return m if update else None
예제 #4
0
 def version(self):
     if self.__version is None:
         conf = Configuration.Configuration()
         sys_mani = conf.SystemManifest()
         if sys_mani:
             self.__version = sys_mani.Version()
     return self.__version
예제 #5
0
def PendingUpdates(directory):
    """
    Return a list (a la CheckForUpdates handler right now) of
    changes between the currently installed system and the
    downloaded contents in <directory>.  If <directory>'s values
    are incomplete or invalid for whatever reason, return
    None.  "Incomplete" means a necessary file for upgrading
    from the current system is not present; "Invalid" means that
    one part of it is invalid -- manifest is not valid, signature isn't
    valid, checksum for a file is invalid, or the stashed sequence
    number does not match the current system's sequence.
    """
    mani_file = None
    conf = Configuration.Configuration()
    try:
        mani_file = VerifyUpdate(directory)
    except UpdateBusyCacheException:
        log.debug("Cache directory %s is busy, so no update available" %
                  directory)
        return None
    except (UpdateIncompleteCacheException, UpdateInvalidCacheException) as e:
        log.error(str(e))
        RemoveUpdate(directory)
        return None
    except BaseException as e:
        log.error(
            "Got exception %s while trying to determine pending updates" %
            str(e))
        return None
    if mani_file:
        new_manifest = Manifest.Manifest()
        new_manifest.LoadFile(mani_file)
        diffs = Manifest.CompareManifests(conf.SystemManifest(), new_manifest)
        return diffs
    return None
예제 #6
0
def sw_version_is_stable():
    conf = Configuration.Configuration()
    train = conf.CurrentTrain()
    if train and 'stable' in train.lower():
        return True
    else:
        return False
예제 #7
0
파일: update.py 프로젝트: MrYHM/freenas
    def download(self, job):
        train = self.middleware.call_sync('update.get_trains')['selected']
        location = self.middleware.call_sync('update.get_update_location')

        job.set_progress(0, 'Retrieving update manifest')

        handler = UpdateHandler(self, job, 100)

        Update.DownloadUpdate(
            train,
            location,
            check_handler=handler.check_handler,
            get_handler=handler.get_handler,
        )
        update = Update.CheckForUpdates(train=train, cache_dir=location)

        if not update:
            return False

        notified = False
        try:
            if self.middleware.call_sync('cache.has_key', 'update.notified'):
                notified = self.middleware.call_sync('cache.get',
                                                     'update.notified')
        except Exception:
            pass

        if not notified:
            self.middleware.call_sync('cache.put', 'update.notified', True)
            conf = Configuration.Configuration()
            sys_mani = conf.SystemManifest()
            if sys_mani:
                sequence = sys_mani.Sequence()
            else:
                sequence = ''

            changelog = get_changelog(train,
                                      start=sequence,
                                      end=update.Sequence())

            try:
                # FIXME: Translation
                self.middleware.call_sync(
                    'mail.send', {
                        'subject': 'Update Available',
                        'text':
                        '''A new update is available for the %(train)s train.
Version: %(version)s
Changelog:
%(changelog)s
''' % {
                            'train': train,
                            'version': update.Version(),
                            'changelog': changelog,
                        },
                    }).wait_sync()
            except Exception:
                self.logger.warn('Failed to send email about new update',
                                 exc_info=True)
        return True
예제 #8
0
파일: update.py 프로젝트: xpcom-bsd/freenas
    def check_available(self, attrs=None):
        """
        Checks if there is an update available from update server.

        status:
          - REBOOT_REQUIRED: an update has already been applied
          - AVAILABLE: an update is available
          - UNAVAILABLE: no update available

        .. examples(websocket)::

          Check available update using default train:

            :::javascript
            {
                "id": "6841f242-840a-11e6-a437-00e04d680384",
                "msg": "method",
                "method": "update.check_available"
            }
        """

        try:
            applied = self.middleware.call_sync('cache.get', 'update.applied')
        except Exception:
            applied = False
        if applied is True:
            return {'status': 'REBOOT_REQUIRED'}

        train = (attrs or {}).get('train') or self.middleware.call_sync(
            'update.get_trains')['selected']

        handler = CheckUpdateHandler()
        manifest = CheckForUpdates(
            diff_handler=handler.diff_call,
            handler=handler.call,
            train=train,
        )

        if not manifest:
            return {'status': 'UNAVAILABLE'}

        data = {
            'status': 'AVAILABLE',
            'changes': handler.changes,
            'notice': manifest.Notice(),
            'notes': manifest.Notes(),
        }

        conf = Configuration.Configuration()
        sys_mani = conf.SystemManifest()
        if sys_mani:
            sequence = sys_mani.Sequence()
        else:
            sequence = ''
        data['changelog'] = get_changelog(train,
                                          start=sequence,
                                          end=manifest.Sequence())

        data['version'] = manifest.Version()
        return data
예제 #9
0
파일: update.py 프로젝트: xpcom-bsd/freenas
    def get_trains(self):
        """
        Returns available trains dict and the currently configured train as well as the
        train of currently booted environment.
        """
        data = self.middleware.call_sync('datastore.config', 'system.update')
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()

        selected = None
        trains = {}
        for name, descr in (conf.AvailableTrains() or {}).items():
            train = conf._trains.get(name)
            if train is None:
                train = Train.Train(name, descr)
            if not selected and data['upd_train'] == train.Name():
                selected = data['upd_train']
            trains[train.Name()] = {
                'description': train.Description(),
                'sequence': train.LastSequence(),
            }
        if not data['upd_train'] or not selected:
            selected = conf.CurrentTrain()
        return {
            'trains': trains,
            'current': conf.CurrentTrain(),
            'selected': selected,
        }
예제 #10
0
def get_changelog(train, start='', end=''):
    conf = Configuration.Configuration()
    changelog = conf.GetChangeLog(train=train)
    if not changelog:
        return None

    return parse_changelog(changelog.read(), start, end)
예제 #11
0
    def trains(self):
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        trains = conf.AvailableTrains()

        if trains is None:
            logger.debug(
                'The AvailableTrains call returned None. Check your network connection'
            )
            return None
        seltrain = self.dispatcher.configstore.get('update.train')

        data = []
        for name in list(trains.keys()):
            if name in conf._trains:
                train = conf._trains.get(name)
            else:
                train = Train.Train(name)
            data.append({
                'name': train.Name(),
                'description': train.Description(),
                'sequence': train.LastSequence(),
                'current': True if name == seltrain else False,
            })
        return data
예제 #12
0
def CheckForUpdates(root = None, handler = None):
    """
    Check for an updated manifest.
    Very simple, uses the configuration module.
    Returns the new manifest if there is an update,
    and None otherwise.
    (It determines if there is an update if the latest-found
    manifeset's sequence number is larger than the current
    sequence number.)
    The optional argument handler is a function that
    will be called for each difference in the new manifest
    (if there is one); it will be called with three
    arguments:  operation, package, old package.
    operation will be "delete", "upgrade", or "install";
    old package will be None for delete and install.
    """
    conf = Configuration.Configuration(root)
    cur = conf.SystemManifest()
    m = conf.FindLatestManifest()
    print >> sys.stderr, "Current sequence = %d, available sequence = %d" % (cur.Sequence(), m.Sequence() if m is not None else 0)
    if m is not None and m.Sequence() > cur.Sequence():
        if handler is not None:
            diffs = Manifest.CompareManifests(cur, m)
            for (pkg, op, old) in diffs:
                handler(op, pkg, old)
        return m
    return None
예제 #13
0
def _system_info(request=None):
    # OS, hostname, release
    __, hostname, __ = os.uname()[0:3]
    platform = sysctl.filter('hw.model')[0].value
    physmem = '%dMB' % (sysctl.filter('hw.physmem')[0].value / 1048576, )
    # All this for a timezone, because time.asctime() doesn't add it in.
    date = time.strftime('%a %b %d %H:%M:%S %Z %Y') + '\n'
    uptime = subprocess.check_output(
        "env -u TZ uptime | awk -F', load averages:' '{ print $1 }'",
        shell=True)
    loadavg = "%.2f, %.2f, %.2f" % os.getloadavg()

    try:
        freenas_build = '%s %s' % (get_sw_name(), get_sw_login_version())
    except:
        freenas_build = "Unrecognized build"

    try:
        conf = Configuration.Configuration()
        manifest = conf.SystemManifest()
        builddate = datetime.utcfromtimestamp(int(manifest.Sequence()))
    except:
        builddate = None

    return {
        'hostname': hostname,
        'platform': platform,
        'physmem': physmem,
        'date': date,
        'uptime': uptime,
        'loadavg': loadavg,
        'freenas_build': freenas_build,
        'builddate': builddate,
    }
예제 #14
0
    def send_telemetry(self):
        logger.info(
            'Uploading telemetry data to {0}'.format(TELEMETRY_ENDPOINT_PATH))
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        manifest = conf.SystemManifest()
        headers = {
            'X-iXSystems-Project': Configuration.Avatar(),
            'X-iXSystems-Version': manifest.Version(),
            'X-iXSystems-HostID': self.hostuuid,
            'X-iXSystems-Train': conf.CurrentTrain()
        }

        manifest = {
            'host_uuid': self.hostuuid,
            'cpu_type': sysctl.sysctlbyname("hw.model"),
            'cpu_clock': sysctl.sysctlbyname("hw.clockrate"),
            'cpu_cores': sysctl.sysctlbyname("hw.ncpu"),
            'hypervisor': sysctl.sysctlbyname("kern.vm_guest"),
            'mem_size': sysctl.sysctlbyname("hw.physmem")
        }

        files = {
            name: open(os.path.join(TELEMETRY_STAGING_PATH, name), 'rb')
            for name in os.listdir(TELEMETRY_STAGING_PATH)
        }

        files['manifest'] = (None, json.dumps(manifest), 'application/json')

        try:
            requests.post(TELEMETRY_ENDPOINT_PATH,
                          headers=headers,
                          files=files)
        except BaseException as err:
            logger.error('Cannot send telemerty data: {0}'.format(str(err)))
예제 #15
0
def sw_buildtime():
    global BUILDTIME
    if BUILDTIME is None:
        conf = Configuration.Configuration()
        sys_mani = conf.SystemManifest()
        if sys_mani:
            BUILDTIME = sys_mani.TimeStamp()
    return BUILDTIME
예제 #16
0
 def get_config(self):
     configuration = Configuration.Configuration()
     return {
         'train': self.dispatcher.configstore.get('update.train'),
         'check_auto': self.dispatcher.configstore.get('update.check_auto'),
         'internal': configuration.UpdateServerName() == 'internal',
         'update_server': configuration.UpdateServerURL(),
     }
예제 #17
0
def sw_version_is_stable():

    conf = Configuration.Configuration()

    if 'stable' in conf.CurrentTrain().lower():
        return True
    else:
        return False
예제 #18
0
def sw_version():
    global VERSION
    if VERSION is None:
        conf = Configuration.Configuration()
        sys_mani = conf.SystemManifest()
        if sys_mani:
            VERSION = sys_mani.Version()
    return VERSION
예제 #19
0
def get_changelog(train, cache_dir='/var/tmp/update', start='', end=''):
    "Utility to get and eventually parse a changelog if available"
    conf = Configuration.Configuration()
    changelog = conf.GetChangeLog(train=train, save_dir=cache_dir)
    if not changelog:
        return None

    return parse_changelog(changelog.read(), start, end)
예제 #20
0
def main():

    try:
        updateobj = mUpdate.objects.order_by('-id')[0]
    except IndexError:
        updateobj = mUpdate.objects.create()

    if updateobj.upd_autocheck is False:
        return

    location = notifier().get_update_location()

    Update.DownloadUpdate(updateobj.get_train(), location)

    update = Update.CheckForUpdates(
        train=updateobj.get_train(),
        cache_dir=location,
    )

    if not update:
        return

    conf = Configuration.Configuration()
    sys_mani = conf.SystemManifest()
    if sys_mani:
        sequence = sys_mani.Sequence()
    else:
        sequence = ''

    changelog = get_changelog(
        updateobj.get_train(),
        start=sequence,
        end=update.Sequence(),
    )

    hostname = socket.gethostname()

    send_mail(
        subject='%s: %s' % (
            hostname,
            _('Update Available'),
        ),
        extra_headers={
            'X-Mailer': get_sw_name(),
            'X-%s-Host' % get_sw_name(): socket.gethostname()
        },
        text=_('''A new update is available for the %(train)s train.

Version: %(version)s
Changelog:
%(changelog)s
''') % {
            'train': updateobj.get_train(),
            'version': update.Version(),
            'changelog': changelog,
        },
    )
예제 #21
0
def sw_version_is_stable():
    # Lazy import to avoid freenasOS configure logging for us
    from freenasOS import Configuration
    conf = Configuration.Configuration()
    train = conf.CurrentTrain()
    if train and 'stable' in train.lower():
        return True
    else:
        return False
예제 #22
0
파일: update.py 프로젝트: yiqideren/freenas
    async def download(self, job):
        train = (await self.get_trains())['selected']
        location = await self.middleware.call('notifier.get_update_location')

        Update.DownloadUpdate(
            train,
            location,
        )
        update = Update.CheckForUpdates(train=train, cache_dir=location)

        if not update:
            return False

        notified = False
        try:
            if await self.middleware.call('cache.has_key', 'update.notified'):
                notified = await self.middleware.call('cache.get',
                                                      'update.notified')
        except Exception:
            pass

        if not notified:
            await self.middleware.call('cache.put', 'update.notified', True)
            conf = Configuration.Configuration()
            sys_mani = conf.SystemManifest()
            if sys_mani:
                sequence = sys_mani.Sequence()
            else:
                sequence = ''

            changelog = get_changelog(train,
                                      start=sequence,
                                      end=update.Sequence())
            hostname = socket.gethostname()

            try:
                # FIXME: Translation
                await self.middleware.call(
                    'mail.send', {
                        'subject': '{}: {}'.format(hostname,
                                                   'Update Available'),
                        'text':
                        '''A new update is available for the %(train)s train.
Version: %(version)s
Changelog:
%(changelog)s
''' % {
                            'train': train,
                            'version': update.Version(),
                            'changelog': changelog,
                        },
                    })
            except Exception:
                self.logger.warn('Failed to send email about new update',
                                 exc_info=True)
        return True
예제 #23
0
def sw_version():
    # Lazy import to avoid freenasOS configure logging for us
    from freenasOS import Configuration
    global VERSION
    if VERSION is None:
        conf = Configuration.Configuration()
        sys_mani = conf.SystemManifest()
        if sys_mani:
            VERSION = sys_mani.Version()
    return VERSION
예제 #24
0
def sw_buildtime():
    # Lazy import to avoid freenasOS configure logging for us
    from freenasOS import Configuration
    global BUILDTIME
    if BUILDTIME is None:
        conf = Configuration.Configuration()
        sys_mani = conf.SystemManifest()
        if sys_mani:
            BUILDTIME = sys_mani.TimeStamp()
    return BUILDTIME
예제 #25
0
 def get_train(self):
     # FIXME: lazy import, why?
     from freenasOS import Configuration
     conf = Configuration.Configuration()
     conf.LoadTrainsConfig()
     trains = conf.AvailableTrains() or []
     if trains:
         trains = list(trains.keys())
     if not self.upd_train or self.upd_train not in trains:
         return conf.CurrentTrain()
     return self.upd_train
예제 #26
0
파일: update.py 프로젝트: stattin42/freenas
    def get_trains(self):
        """
        Returns available trains dict and the currently configured train as well as the
        train of currently booted environment.
        """
        data = self.middleware.call_sync('datastore.config', 'system.update')
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()

        try:
            redir_trains = self._get_redir_trains()
        except Exception:
            self.logger.warn('Failed to retrieve trains redirection',
                             exc_info=True)
            redir_trains = {}

        selected = None
        trains = {}
        for name, descr in (conf.AvailableTrains() or {}).items():
            train = conf._trains.get(name)
            if train is None:
                train = Train.Train(name, descr)

            try:
                result = compare_trains(conf.CurrentTrain(), train.Name())
            except Exception:
                self.logger.warning("Failed to compare trains %r and %r",
                                    conf.CurrentTrain(),
                                    train.Name(),
                                    exc_info=True)
                continue
            else:
                if result in BAD_UPGRADES:
                    continue

            if not selected and data['upd_train'] == train.Name():
                selected = data['upd_train']
            if name in redir_trains:
                continue
            trains[train.Name()] = {
                'description': descr,
                'sequence': train.LastSequence(),
            }
        if not data['upd_train'] or not selected:
            selected = conf.CurrentTrain()

        if selected in redir_trains:
            selected = redir_trains[selected]
        return {
            'trains': trains,
            'current': conf.CurrentTrain(),
            'selected': selected,
        }
예제 #27
0
 def get_train(self):
     """
     Returns currently configured train
     """
     data = self.middleware.call('datastore.config', 'system.update')
     conf = Configuration.Configuration()
     conf.LoadTrainsConfig()
     trains = conf.AvailableTrains() or []
     if trains:
         trains = trains.keys()
     if not data['upd_train'] or data['upd_train'] not in trains:
         return conf.CurrentTrain()
예제 #28
0
    def version(self):
        if self.__version is None:
            # See #9113
            conf = Configuration.Configuration()
            manifest = conf.SystemManifest()
            if manifest:
                self.__version = manifest.Version()
            else:
                with open(VERSION_FILE) as fd:
                    self.__version = fd.read().strip()

        return self.__version
예제 #29
0
    def install_impl(self, job, location):
        old_manifest = Configuration.Configuration().SystemManifest()

        new_manifest = Manifest.Manifest(require_signature=True)
        new_manifest.LoadPath('{}/MANIFEST'.format(location))

        old_version = old_manifest.Version()
        new_version = new_manifest.Version()
        if not can_update(old_version, new_version):
            raise CallError(f'Unable to downgrade from {old_version} to {new_version}')

        return self.middleware.call_sync('update.install_impl_job', job.id, location).wait_sync(raise_error=True)
예제 #30
0
def CheckForUpdates(root=None, handler=None, train=None, cache_dir=None):
    """
    Check for an updated manifest.
    Very simple, uses the configuration module.
    Returns the new manifest if there is an update,
    and None otherwise.
    (It determines if there is an update if the latest-found
    manifest contains differences from the current system
    manifest.)
    The optional argument handler is a function that
    will be called for each difference in the new manifest
    (if there is one); it will be called with three
    arguments:  operation, package, old package.
    operation will be "delete", "upgrade", or "install";
    old package will be None for delete and install.
    The optional cache_dir parameter indicates that it
    should look in that directory first, rather than
    going over the network.  (Unlike the similar code
    in freenas-update, this will not [at this time]
    download the package files and store them in
    cache_dir.)
    """
    conf = Configuration.Configuration(root)
    cur = conf.SystemManifest()
    m = None
    # Let's check cache_dir if it is set
    if cache_dir and (not train or train == cur.Train()):
        if os.path.exists(cache_dir + "/MANIFEST"):
            # Okay, let's load it up.
            m = Manifest.Manifest()
            try:
                m.LoadPath(cache_dir + "/MANIFEST")
                if m.Train() != cur.Train():
                    # Should we get rid of the cache?
                    m = None
            except:
                m = None

    if m is None:
        m = conf.FindLatestManifest(train=train)

    log.debug("Current sequence = %s, available sequence = %s" %
              (cur.Sequence(), m.Sequence() if m is not None else "None"))
    if m is None:
        raise ValueError("Manifest could not be found!")
    diffs = Manifest.CompareManifests(cur, m)
    update = False
    for (pkg, op, old) in diffs:
        update = True
        if handler is not None:
            handler(op, pkg, old)
    return m if update else None