func (d *Downloader) downloadMissingVideos(log *logrus.Entry) { // Fetch wishlist wl := polochon.NewWishlist(d.config.Wishlist, log) if err := wl.Fetch(); err != nil { log.Errorf("got an error while fetching wishlist: %q", err) return } d.downloadMissingMovies(wl, log) d.downloadMissingShows(wl, log) }
func logWriterScanner(logger *logrus.Entry, reader *io.PipeReader) { defer reader.Close() scanner := bufio.NewScanner(reader) for scanner.Scan() { logger.Print(scanner.Text()) } if err := scanner.Err(); err != nil { if err == io.EOF { return } logger.Errorf("Error while reading from Writer: %s", err) } }
func (l *Library) scanEpisodes(imdbID, showRootPath string, log *logrus.Entry) error { // Walk the files of a show err := filepath.Walk(showRootPath, func(filePath string, file os.FileInfo, err error) error { // Check err if err != nil { log.Errorf("library: failed to walk %q", err) return nil } // Nothing to do on dir if file.IsDir() { return nil } // search for show type ext := path.Ext(filePath) var epPath string for _, mext := range l.fileConfig.VideoExtentions { if ext == mext { epPath = filePath break } } if epPath == "" { return nil } // Read the nfo file episode, err := l.newEpisodeFromPath(epPath) if err != nil { log.Errorf("library: failed to read episode NFO: %q", err) return nil } episode.ShowImdbID = imdbID episode.ShowConfig = l.showConfig l.showIndex.Add(episode) return nil }) if err != nil { return err } return nil }
// startFsNotifier starts the FsNotifier func (o *Organizer) startFsNotifier(log *logrus.Entry) error { ctx := polochon.FsNotifierCtx{ Event: o.event, Done: o.Done, Wg: &o.Wg, } // Send a notification to organize the whole folder on app start watcherPath := o.config.Watcher.Dir ctx.Event <- watcherPath // Launch the FsNotifier if err := o.config.Watcher.FsNotifier.Watch(watcherPath, ctx, log); err != nil { return err } var err error o.Wg.Add(1) go func() { defer func() { o.Wg.Done() if r := recover(); r != nil { err = errors.New("panic recovered").Fatal().AddContext(errors.Context{ "sub_app": AppName, }) o.Stop(log) } }() for { select { case file := <-ctx.Event: log.WithField("event", file).Debugf("got an event") if err := o.organize(file, log); err != nil { log.Errorf("failed to organize file: %q", err) } case <-o.Done: log.Debug("organizer done handling events") return } } }() o.Wg.Wait() return err }
func (l *Library) buildMovieIndex(log *logrus.Entry) error { start := time.Now() err := filepath.Walk(l.MovieDir, func(filePath string, file os.FileInfo, err error) error { // Check err if err != nil { log.Errorf("library: failed to walk %q", err) return nil } // Nothing to do on dir if file.IsDir() { return nil } // search for movie type ext := path.Ext(filePath) var moviePath string for _, mext := range l.fileConfig.VideoExtentions { if ext == mext { moviePath = filePath break } } if moviePath == "" { return nil } // Read the movie informations movie, err := l.newMovieFromPath(moviePath) if err != nil { log.Errorf("library: failed to read movie NFO: %q", err) return nil } // Add the movie to the index l.movieIndex.Add(movie) return nil }) log.Infof("Index built in %s", time.Since(start)) return err }
func (l *Library) buildShowIndex(log *logrus.Entry) error { start := time.Now() // used to catch if the first root folder has been walked var rootWalked bool // Get only the parent folders err := filepath.Walk(l.ShowDir, func(filePath string, file os.FileInfo, err error) error { // Only check directories if !file.IsDir() { return nil } // The root folder is only walk once if !rootWalked { rootWalked = true return nil } // Check if we can find the tvshow.nfo file nfoPath := l.showNFOPath(filePath) show, err := l.newShowFromPath(nfoPath) if err != nil { log.Errorf("library: failed to read tv show NFO: %q", err) return nil } // Scan the path for the episodes err = l.scanEpisodes(show.ImdbID, filePath, log) if err != nil { return err } // No need to go deeper, the tvshow.nfo is in the second root folder return filepath.SkipDir }) if err != nil { return err } log.Infof("Index built in %s", time.Since(start)) return nil }
func (c *Cleaner) cleanDoneVideos(log *logrus.Entry) { list, err := c.config.Downloader.Client.List() if err != nil { log.Errorf("error while getting torrent list: %q", err) return } for _, t := range list { torrentInfos := t.Infos() log = log.WithField("torrent_name", torrentInfos.Name) // Check if the file is ready to be cleaned isReady := c.isReadyToBeCleaned(t, log) if !isReady { log.Debug("torrent is not ready to be cleaned") continue } // We remove the torrent log.Debugf("removing torrent") err := c.config.Downloader.Client.Remove(t) if err != nil { log.Errorf("got error when removing torrent : %q", err) continue } log.Debug("removing files") if err = c.clean(t, log); err != nil { log.Errorf("failed to clean torrent files: %q", err) continue } } }
// parse an 'app' tag of request and generate a corresponding 'app' tag of response func handleApiApp(logContext *logrus.Entry, localUrl string, appRequest, appResponse *omaha.App) { logContext = logContext.WithFields(logrus.Fields{ "machineId": appRequest.MachineID, }) if appRequest.Id != coreOSAppID { appResponse.Status = "error-unknownApplication" } else { appResponse.Status = "ok" } // <UpdateCheck> tag if appRequest.UpdateCheck != nil { logContext.Debug("Handling UpdateCheck") ucResp := appResponse.AddUpdateCheck() appVersion, err := parseVersionString(appRequest.Version) if err != nil { logContext.Errorf("Could not parse client's version string: %v", err.Error()) ucResp.Status = "error-invalidVersionString" } else { handleApiUpdateCheck(logContext, localUrl, appVersion, appRequest.Track, appRequest.UpdateCheck, ucResp) } } // <ping> tag if appRequest.Ping != nil { // TODO register info from the ping // response is always "ok" according to the specs responsePing := appResponse.AddPing() responsePing.Status = "ok" } // <Event> tag handleApiEvents(logContext, appRequest.MachineID, appRequest.Events) }
// parse an 'UpdateCheck' tag of request and generate a corresponding 'UpdateCheck' tag of response func handleApiUpdateCheck(logContext *logrus.Entry, localUrl string, appVersion payloadVersion, channel string, ucRequest, ucResp *omaha.UpdateCheck) { payload, err := db.GetNewerPayload(appVersion, channel) if err != nil { logContext.Errorf("Failed checking for newer payload: %v", err.Error()) ucResp.Status = "error-internal" } else { if payload == nil { logContext.Infof("Client already up-to-date") ucResp.Status = "noupdate" return } logContext.Infof("Found update to version '%v' (id %v)", payload.Version, payload.ID) ucResp.Status = "ok" ucResp.AddUrl(fileBE.GetUpdateURL(localUrl)) manifest := ucResp.AddManifest("1.0.2") manifest.AddPackage(payload.SHA1, payload.ID, strconv.FormatInt(payload.Size, 10), true) action := manifest.AddAction("postinstall") action.Sha256 = payload.SHA256 action.DisablePayloadBackoff = true } }
// DoNetworking performs the networking for the given config and IPAM result func DoNetworking(args *skel.CmdArgs, conf NetConf, res *types.Result, logger *log.Entry, desiredVethName string) (hostVethName, contVethMAC string, err error) { // Select the first 11 characters of the containerID for the host veth. hostVethName = "cali" + args.ContainerID[:min(11, len(args.ContainerID))] contVethName := args.IfName // If a desired veth name was passed in, use that instead. if desiredVethName != "" { hostVethName = desiredVethName } err = ns.WithNetNSPath(args.Netns, func(hostNS ns.NetNS) error { veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{ Name: contVethName, Flags: net.FlagUp, MTU: conf.MTU, }, PeerName: hostVethName, } if err := netlink.LinkAdd(veth); err != nil { logger.Errorf("Error adding veth %+v: %s", veth, err) return err } hostVeth, err := netlink.LinkByName(hostVethName) if err != nil { err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err) return err } contVeth, err := netlink.LinkByName(contVethName) if err != nil { err = fmt.Errorf("failed to lookup %q: %v", contVethName, err) return err } // Fetch the MAC from the container Veth. This is needed by Calico. contVethMAC = contVeth.Attrs().HardwareAddr.String() logger.WithField("MAC", contVethMAC).Debug("Found MAC for container veth") // At this point, the virtual ethernet pair has been created, and both ends have the right names. // Both ends of the veth are still in the container's network namespace. // Before returning, create the routes inside the namespace, first for IPv4 then IPv6. if res.IP4 != nil { // Add a connected route to a dummy next hop so that a default route can be set gw := net.IPv4(169, 254, 1, 1) gwNet := &net.IPNet{IP: gw, Mask: net.CIDRMask(32, 32)} if err = netlink.RouteAdd(&netlink.Route{ LinkIndex: contVeth.Attrs().Index, Scope: netlink.SCOPE_LINK, Dst: gwNet}); err != nil { return fmt.Errorf("failed to add route %v", err) } if err = ip.AddDefaultRoute(gw, contVeth); err != nil { return fmt.Errorf("failed to add route %v", err) } if err = netlink.AddrAdd(contVeth, &netlink.Addr{IPNet: &res.IP4.IP}); err != nil { return fmt.Errorf("failed to add IP addr to %q: %v", contVethName, err) } } // Handle IPv6 routes if res.IP6 != nil { // No need to add a dummy next hop route as the host veth device will already have an IPv6 // link local address that can be used as a next hop. // Just fetch the address of the host end of the veth and use it as the next hop. var hostIPv6Addr net.IP if err := hostNS.Do(func(_ ns.NetNS) error { addresses, err := netlink.AddrList(hostVeth, netlink.FAMILY_V6) if err != nil { logger.Errorf("Error listing IPv6 addresses: %s", err) return err } if len(addresses) < 1 { // If the hostVeth doesn't have an IPv6 address then this host probably doesn't // support IPv6. Since a IPv6 address has been allocated that can't be used, // return an error. return fmt.Errorf("Failed to get IPv6 addresses for container veth") } hostIPv6Addr = addresses[0].IP return nil }); err != nil { logger.Errorf("Error getting IPv6 address: %s", err) return err } _, defNet, _ := net.ParseCIDR("::/0") if err = ip.AddRoute(defNet, hostIPv6Addr, contVeth); err != nil { return fmt.Errorf("failed to add default gateway to %v %v", hostIPv6Addr, err) } if err = netlink.AddrAdd(contVeth, &netlink.Addr{IPNet: &res.IP6.IP}); err != nil { return fmt.Errorf("failed to add IP addr to %q: %v", contVeth, err) } } // Now that the everything has been successfully set up in the container, move the "host" end of the // veth into the host namespace. if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil { return fmt.Errorf("failed to move veth to host netns: %v", err) } return nil }) if err != nil { logger.Errorf("Error creating veth: %s", err) return "", "", err } // Moving a veth between namespaces always leaves it in the "DOWN" state. Set it back to "UP" now that we're // back in the host namespace. hostVeth, err := netlink.LinkByName(hostVethName) if err != nil { return "", "", fmt.Errorf("failed to lookup %q: %v", hostVethName, err) } if err = netlink.LinkSetUp(hostVeth); err != nil { return "", "", fmt.Errorf("failed to set %q up: %v", hostVethName, err) } return hostVethName, contVethMAC, err }