utils.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. package utils
  2. import (
  3. "bytes"
  4. "crypto/sha1"
  5. "crypto/sha256"
  6. "encoding/hex"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "index/suffixarray"
  11. "io"
  12. "io/ioutil"
  13. "net/http"
  14. "os"
  15. "os/exec"
  16. "path/filepath"
  17. "regexp"
  18. "runtime"
  19. "strconv"
  20. "strings"
  21. "sync"
  22. "time"
  23. )
  24. var (
  25. IAMSTATIC bool // whether or not Docker itself was compiled statically via ./hack/make.sh binary
  26. INITSHA1 string // sha1sum of separate static dockerinit, if Docker itself was compiled dynamically via ./hack/make.sh dynbinary
  27. )
  28. // ListOpts type
  29. type ListOpts []string
  30. func (opts *ListOpts) String() string {
  31. return fmt.Sprint(*opts)
  32. }
  33. func (opts *ListOpts) Set(value string) error {
  34. *opts = append(*opts, value)
  35. return nil
  36. }
  37. // Go is a basic promise implementation: it wraps calls a function in a goroutine,
  38. // and returns a channel which will later return the function's return value.
  39. func Go(f func() error) chan error {
  40. ch := make(chan error)
  41. go func() {
  42. ch <- f()
  43. }()
  44. return ch
  45. }
  46. // Request a given URL and return an io.Reader
  47. func Download(url string, stderr io.Writer) (*http.Response, error) {
  48. var resp *http.Response
  49. var err error
  50. if resp, err = http.Get(url); err != nil {
  51. return nil, err
  52. }
  53. if resp.StatusCode >= 400 {
  54. return nil, errors.New("Got HTTP status code >= 400: " + resp.Status)
  55. }
  56. return resp, nil
  57. }
  58. func logf(level string, format string, a ...interface{}) {
  59. // Retrieve the stack infos
  60. _, file, line, ok := runtime.Caller(2)
  61. if !ok {
  62. file = "<unknown>"
  63. line = -1
  64. } else {
  65. file = file[strings.LastIndex(file, "/")+1:]
  66. }
  67. fmt.Fprintf(os.Stderr, fmt.Sprintf("[%s] %s:%d %s\n", level, file, line, format), a...)
  68. }
  69. // Debug function, if the debug flag is set, then display. Do nothing otherwise
  70. // If Docker is in damon mode, also send the debug info on the socket
  71. func Debugf(format string, a ...interface{}) {
  72. if os.Getenv("DEBUG") != "" {
  73. logf("debug", format, a...)
  74. }
  75. }
  76. func Errorf(format string, a ...interface{}) {
  77. logf("error", format, a...)
  78. }
  79. // Reader with progress bar
  80. type progressReader struct {
  81. reader io.ReadCloser // Stream to read from
  82. output io.Writer // Where to send progress bar to
  83. readTotal int // Expected stream length (bytes)
  84. readProgress int // How much has been read so far (bytes)
  85. lastUpdate int // How many bytes read at least update
  86. template string // Template to print. Default "%v/%v (%v)"
  87. sf *StreamFormatter
  88. newLine bool
  89. }
  90. func (r *progressReader) Read(p []byte) (n int, err error) {
  91. read, err := io.ReadCloser(r.reader).Read(p)
  92. r.readProgress += read
  93. updateEvery := 1024 * 512 //512kB
  94. if r.readTotal > 0 {
  95. // Update progress for every 1% read if 1% < 512kB
  96. if increment := int(0.01 * float64(r.readTotal)); increment < updateEvery {
  97. updateEvery = increment
  98. }
  99. }
  100. if r.readProgress-r.lastUpdate > updateEvery || err != nil {
  101. if r.readTotal > 0 {
  102. fmt.Fprintf(r.output, r.template, HumanSize(int64(r.readProgress)), HumanSize(int64(r.readTotal)), fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100))
  103. } else {
  104. fmt.Fprintf(r.output, r.template, r.readProgress, "?", "n/a")
  105. }
  106. r.lastUpdate = r.readProgress
  107. }
  108. // Send newline when complete
  109. if r.newLine && err != nil {
  110. r.output.Write(r.sf.FormatStatus("", ""))
  111. }
  112. return read, err
  113. }
  114. func (r *progressReader) Close() error {
  115. return io.ReadCloser(r.reader).Close()
  116. }
  117. func ProgressReader(r io.ReadCloser, size int, output io.Writer, tpl []byte, sf *StreamFormatter, newline bool) *progressReader {
  118. return &progressReader{
  119. reader: r,
  120. output: NewWriteFlusher(output),
  121. readTotal: size,
  122. template: string(tpl),
  123. sf: sf,
  124. newLine: newline,
  125. }
  126. }
  127. // HumanDuration returns a human-readable approximation of a duration
  128. // (eg. "About a minute", "4 hours ago", etc.)
  129. func HumanDuration(d time.Duration) string {
  130. if seconds := int(d.Seconds()); seconds < 1 {
  131. return "Less than a second"
  132. } else if seconds < 60 {
  133. return fmt.Sprintf("%d seconds", seconds)
  134. } else if minutes := int(d.Minutes()); minutes == 1 {
  135. return "About a minute"
  136. } else if minutes < 60 {
  137. return fmt.Sprintf("%d minutes", minutes)
  138. } else if hours := int(d.Hours()); hours == 1 {
  139. return "About an hour"
  140. } else if hours < 48 {
  141. return fmt.Sprintf("%d hours", hours)
  142. } else if hours < 24*7*2 {
  143. return fmt.Sprintf("%d days", hours/24)
  144. } else if hours < 24*30*3 {
  145. return fmt.Sprintf("%d weeks", hours/24/7)
  146. } else if hours < 24*365*2 {
  147. return fmt.Sprintf("%d months", hours/24/30)
  148. }
  149. return fmt.Sprintf("%f years", d.Hours()/24/365)
  150. }
  151. // HumanSize returns a human-readable approximation of a size
  152. // using SI standard (eg. "44kB", "17MB")
  153. func HumanSize(size int64) string {
  154. i := 0
  155. var sizef float64
  156. sizef = float64(size)
  157. units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
  158. for sizef >= 1000.0 {
  159. sizef = sizef / 1000.0
  160. i++
  161. }
  162. return fmt.Sprintf("%.4g %s", sizef, units[i])
  163. }
  164. // Parses a human-readable string representing an amount of RAM
  165. // in bytes, kibibytes, mebibytes or gibibytes, and returns the
  166. // number of bytes, or -1 if the string is unparseable.
  167. // Units are case-insensitive, and the 'b' suffix is optional.
  168. func RAMInBytes(size string) (bytes int64, err error) {
  169. re, error := regexp.Compile("^(\\d+)([kKmMgG])?[bB]?$")
  170. if error != nil {
  171. return -1, error
  172. }
  173. matches := re.FindStringSubmatch(size)
  174. if len(matches) != 3 {
  175. return -1, fmt.Errorf("Invalid size: '%s'", size)
  176. }
  177. memLimit, error := strconv.ParseInt(matches[1], 10, 0)
  178. if error != nil {
  179. return -1, error
  180. }
  181. unit := strings.ToLower(matches[2])
  182. if unit == "k" {
  183. memLimit *= 1024
  184. } else if unit == "m" {
  185. memLimit *= 1024 * 1024
  186. } else if unit == "g" {
  187. memLimit *= 1024 * 1024 * 1024
  188. }
  189. return memLimit, nil
  190. }
  191. func Trunc(s string, maxlen int) string {
  192. if len(s) <= maxlen {
  193. return s
  194. }
  195. return s[:maxlen]
  196. }
  197. // Figure out the absolute path of our own binary
  198. func SelfPath() string {
  199. path, err := exec.LookPath(os.Args[0])
  200. if err != nil {
  201. panic(err)
  202. }
  203. path, err = filepath.Abs(path)
  204. if err != nil {
  205. panic(err)
  206. }
  207. return path
  208. }
  209. func dockerInitSha1(target string) string {
  210. f, err := os.Open(target)
  211. if err != nil {
  212. return ""
  213. }
  214. defer f.Close()
  215. h := sha1.New()
  216. _, err = io.Copy(h, f)
  217. if err != nil {
  218. return ""
  219. }
  220. return hex.EncodeToString(h.Sum(nil))
  221. }
  222. func isValidDockerInitPath(target string, selfPath string) bool { // target and selfPath should be absolute (InitPath and SelfPath already do this)
  223. if IAMSTATIC {
  224. if target == selfPath {
  225. return true
  226. }
  227. targetFileInfo, err := os.Lstat(target)
  228. if err != nil {
  229. return false
  230. }
  231. selfPathFileInfo, err := os.Lstat(selfPath)
  232. if err != nil {
  233. return false
  234. }
  235. return os.SameFile(targetFileInfo, selfPathFileInfo)
  236. }
  237. return INITSHA1 != "" && dockerInitSha1(target) == INITSHA1
  238. }
  239. // Figure out the path of our dockerinit (which may be SelfPath())
  240. func DockerInitPath() string {
  241. selfPath := SelfPath()
  242. if isValidDockerInitPath(selfPath, selfPath) {
  243. // if we're valid, don't bother checking anything else
  244. return selfPath
  245. }
  246. var possibleInits = []string{
  247. filepath.Join(filepath.Dir(selfPath), "dockerinit"),
  248. // "/usr/libexec includes internal binaries that are not intended to be executed directly by users or shell scripts. Applications may use a single subdirectory under /usr/libexec."
  249. "/usr/libexec/docker/dockerinit",
  250. "/usr/local/libexec/docker/dockerinit",
  251. }
  252. for _, dockerInit := range possibleInits {
  253. path, err := exec.LookPath(dockerInit)
  254. if err == nil {
  255. path, err = filepath.Abs(path)
  256. if err != nil {
  257. // LookPath already validated that this file exists and is executable (following symlinks), so how could Abs fail?
  258. panic(err)
  259. }
  260. if isValidDockerInitPath(path, selfPath) {
  261. return path
  262. }
  263. }
  264. }
  265. return ""
  266. }
  267. type NopWriter struct{}
  268. func (*NopWriter) Write(buf []byte) (int, error) {
  269. return len(buf), nil
  270. }
  271. type nopWriteCloser struct {
  272. io.Writer
  273. }
  274. func (w *nopWriteCloser) Close() error { return nil }
  275. func NopWriteCloser(w io.Writer) io.WriteCloser {
  276. return &nopWriteCloser{w}
  277. }
  278. type bufReader struct {
  279. sync.Mutex
  280. buf *bytes.Buffer
  281. reader io.Reader
  282. err error
  283. wait sync.Cond
  284. }
  285. func NewBufReader(r io.Reader) *bufReader {
  286. reader := &bufReader{
  287. buf: &bytes.Buffer{},
  288. reader: r,
  289. }
  290. reader.wait.L = &reader.Mutex
  291. go reader.drain()
  292. return reader
  293. }
  294. func (r *bufReader) drain() {
  295. buf := make([]byte, 1024)
  296. for {
  297. n, err := r.reader.Read(buf)
  298. r.Lock()
  299. if err != nil {
  300. r.err = err
  301. } else {
  302. r.buf.Write(buf[0:n])
  303. }
  304. r.wait.Signal()
  305. r.Unlock()
  306. if err != nil {
  307. break
  308. }
  309. }
  310. }
  311. func (r *bufReader) Read(p []byte) (n int, err error) {
  312. r.Lock()
  313. defer r.Unlock()
  314. for {
  315. n, err = r.buf.Read(p)
  316. if n > 0 {
  317. return n, err
  318. }
  319. if r.err != nil {
  320. return 0, r.err
  321. }
  322. r.wait.Wait()
  323. }
  324. }
  325. func (r *bufReader) Close() error {
  326. closer, ok := r.reader.(io.ReadCloser)
  327. if !ok {
  328. return nil
  329. }
  330. return closer.Close()
  331. }
  332. type WriteBroadcaster struct {
  333. sync.Mutex
  334. buf *bytes.Buffer
  335. writers map[StreamWriter]bool
  336. }
  337. type StreamWriter struct {
  338. wc io.WriteCloser
  339. stream string
  340. }
  341. func (w *WriteBroadcaster) AddWriter(writer io.WriteCloser, stream string) {
  342. w.Lock()
  343. sw := StreamWriter{wc: writer, stream: stream}
  344. w.writers[sw] = true
  345. w.Unlock()
  346. }
  347. type JSONLog struct {
  348. Log string `json:"log,omitempty"`
  349. Stream string `json:"stream,omitempty"`
  350. Created time.Time `json:"time"`
  351. }
  352. func (w *WriteBroadcaster) Write(p []byte) (n int, err error) {
  353. w.Lock()
  354. defer w.Unlock()
  355. w.buf.Write(p)
  356. for sw := range w.writers {
  357. lp := p
  358. if sw.stream != "" {
  359. lp = nil
  360. for {
  361. line, err := w.buf.ReadString('\n')
  362. if err != nil {
  363. w.buf.Write([]byte(line))
  364. break
  365. }
  366. b, err := json.Marshal(&JSONLog{Log: line, Stream: sw.stream, Created: time.Now()})
  367. if err != nil {
  368. // On error, evict the writer
  369. delete(w.writers, sw)
  370. continue
  371. }
  372. lp = append(lp, b...)
  373. lp = append(lp, '\n')
  374. }
  375. }
  376. if n, err := sw.wc.Write(lp); err != nil || n != len(lp) {
  377. // On error, evict the writer
  378. delete(w.writers, sw)
  379. }
  380. }
  381. return len(p), nil
  382. }
  383. func (w *WriteBroadcaster) CloseWriters() error {
  384. w.Lock()
  385. defer w.Unlock()
  386. for sw := range w.writers {
  387. sw.wc.Close()
  388. }
  389. w.writers = make(map[StreamWriter]bool)
  390. return nil
  391. }
  392. func NewWriteBroadcaster() *WriteBroadcaster {
  393. return &WriteBroadcaster{writers: make(map[StreamWriter]bool), buf: bytes.NewBuffer(nil)}
  394. }
  395. func GetTotalUsedFds() int {
  396. if fds, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/fd", os.Getpid())); err != nil {
  397. Errorf("Error opening /proc/%d/fd: %s", os.Getpid(), err)
  398. } else {
  399. return len(fds)
  400. }
  401. return -1
  402. }
  403. // TruncIndex allows the retrieval of string identifiers by any of their unique prefixes.
  404. // This is used to retrieve image and container IDs by more convenient shorthand prefixes.
  405. type TruncIndex struct {
  406. index *suffixarray.Index
  407. ids map[string]bool
  408. bytes []byte
  409. }
  410. func NewTruncIndex() *TruncIndex {
  411. return &TruncIndex{
  412. index: suffixarray.New([]byte{' '}),
  413. ids: make(map[string]bool),
  414. bytes: []byte{' '},
  415. }
  416. }
  417. func (idx *TruncIndex) Add(id string) error {
  418. if strings.Contains(id, " ") {
  419. return fmt.Errorf("Illegal character: ' '")
  420. }
  421. if _, exists := idx.ids[id]; exists {
  422. return fmt.Errorf("Id already exists: %s", id)
  423. }
  424. idx.ids[id] = true
  425. idx.bytes = append(idx.bytes, []byte(id+" ")...)
  426. idx.index = suffixarray.New(idx.bytes)
  427. return nil
  428. }
  429. func (idx *TruncIndex) Delete(id string) error {
  430. if _, exists := idx.ids[id]; !exists {
  431. return fmt.Errorf("No such id: %s", id)
  432. }
  433. before, after, err := idx.lookup(id)
  434. if err != nil {
  435. return err
  436. }
  437. delete(idx.ids, id)
  438. idx.bytes = append(idx.bytes[:before], idx.bytes[after:]...)
  439. idx.index = suffixarray.New(idx.bytes)
  440. return nil
  441. }
  442. func (idx *TruncIndex) lookup(s string) (int, int, error) {
  443. offsets := idx.index.Lookup([]byte(" "+s), -1)
  444. //log.Printf("lookup(%s): %v (index bytes: '%s')\n", s, offsets, idx.index.Bytes())
  445. if offsets == nil || len(offsets) == 0 || len(offsets) > 1 {
  446. return -1, -1, fmt.Errorf("No such id: %s", s)
  447. }
  448. offsetBefore := offsets[0] + 1
  449. offsetAfter := offsetBefore + strings.Index(string(idx.bytes[offsetBefore:]), " ")
  450. return offsetBefore, offsetAfter, nil
  451. }
  452. func (idx *TruncIndex) Get(s string) (string, error) {
  453. before, after, err := idx.lookup(s)
  454. //log.Printf("Get(%s) bytes=|%s| before=|%d| after=|%d|\n", s, idx.bytes, before, after)
  455. if err != nil {
  456. return "", err
  457. }
  458. return string(idx.bytes[before:after]), err
  459. }
  460. // TruncateID returns a shorthand version of a string identifier for convenience.
  461. // A collision with other shorthands is very unlikely, but possible.
  462. // In case of a collision a lookup with TruncIndex.Get() will fail, and the caller
  463. // will need to use a langer prefix, or the full-length Id.
  464. func TruncateID(id string) string {
  465. shortLen := 12
  466. if len(id) < shortLen {
  467. shortLen = len(id)
  468. }
  469. return id[:shortLen]
  470. }
  471. // Code c/c from io.Copy() modified to handle escape sequence
  472. func CopyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error) {
  473. buf := make([]byte, 32*1024)
  474. for {
  475. nr, er := src.Read(buf)
  476. if nr > 0 {
  477. // ---- Docker addition
  478. // char 16 is C-p
  479. if nr == 1 && buf[0] == 16 {
  480. nr, er = src.Read(buf)
  481. // char 17 is C-q
  482. if nr == 1 && buf[0] == 17 {
  483. if err := src.Close(); err != nil {
  484. return 0, err
  485. }
  486. return 0, io.EOF
  487. }
  488. }
  489. // ---- End of docker
  490. nw, ew := dst.Write(buf[0:nr])
  491. if nw > 0 {
  492. written += int64(nw)
  493. }
  494. if ew != nil {
  495. err = ew
  496. break
  497. }
  498. if nr != nw {
  499. err = io.ErrShortWrite
  500. break
  501. }
  502. }
  503. if er == io.EOF {
  504. break
  505. }
  506. if er != nil {
  507. err = er
  508. break
  509. }
  510. }
  511. return written, err
  512. }
  513. func HashData(src io.Reader) (string, error) {
  514. h := sha256.New()
  515. if _, err := io.Copy(h, src); err != nil {
  516. return "", err
  517. }
  518. return "sha256:" + hex.EncodeToString(h.Sum(nil)), nil
  519. }
  520. type KernelVersionInfo struct {
  521. Kernel int
  522. Major int
  523. Minor int
  524. Flavor string
  525. }
  526. func (k *KernelVersionInfo) String() string {
  527. flavor := ""
  528. if len(k.Flavor) > 0 {
  529. flavor = fmt.Sprintf("-%s", k.Flavor)
  530. }
  531. return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, flavor)
  532. }
  533. // Compare two KernelVersionInfo struct.
  534. // Returns -1 if a < b, = if a == b, 1 it a > b
  535. func CompareKernelVersion(a, b *KernelVersionInfo) int {
  536. if a.Kernel < b.Kernel {
  537. return -1
  538. } else if a.Kernel > b.Kernel {
  539. return 1
  540. }
  541. if a.Major < b.Major {
  542. return -1
  543. } else if a.Major > b.Major {
  544. return 1
  545. }
  546. if a.Minor < b.Minor {
  547. return -1
  548. } else if a.Minor > b.Minor {
  549. return 1
  550. }
  551. return 0
  552. }
  553. func FindCgroupMountpoint(cgroupType string) (string, error) {
  554. output, err := ioutil.ReadFile("/proc/mounts")
  555. if err != nil {
  556. return "", err
  557. }
  558. // /proc/mounts has 6 fields per line, one mount per line, e.g.
  559. // cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0
  560. for _, line := range strings.Split(string(output), "\n") {
  561. parts := strings.Split(line, " ")
  562. if len(parts) == 6 && parts[2] == "cgroup" {
  563. for _, opt := range strings.Split(parts[3], ",") {
  564. if opt == cgroupType {
  565. return parts[1], nil
  566. }
  567. }
  568. }
  569. }
  570. return "", fmt.Errorf("cgroup mountpoint not found for %s", cgroupType)
  571. }
  572. func GetKernelVersion() (*KernelVersionInfo, error) {
  573. var (
  574. err error
  575. )
  576. uts, err := uname()
  577. if err != nil {
  578. return nil, err
  579. }
  580. release := make([]byte, len(uts.Release))
  581. i := 0
  582. for _, c := range uts.Release {
  583. release[i] = byte(c)
  584. i++
  585. }
  586. // Remove the \x00 from the release for Atoi to parse correctly
  587. release = release[:bytes.IndexByte(release, 0)]
  588. return ParseRelease(string(release))
  589. }
  590. func ParseRelease(release string) (*KernelVersionInfo, error) {
  591. var (
  592. flavor string
  593. kernel, major, minor int
  594. err error
  595. )
  596. tmp := strings.SplitN(release, "-", 2)
  597. tmp2 := strings.Split(tmp[0], ".")
  598. if len(tmp2) > 0 {
  599. kernel, err = strconv.Atoi(tmp2[0])
  600. if err != nil {
  601. return nil, err
  602. }
  603. }
  604. if len(tmp2) > 1 {
  605. major, err = strconv.Atoi(tmp2[1])
  606. if err != nil {
  607. return nil, err
  608. }
  609. }
  610. if len(tmp2) > 2 {
  611. // Removes "+" because git kernels might set it
  612. minorUnparsed := strings.Trim(tmp2[2], "+")
  613. minor, err = strconv.Atoi(minorUnparsed)
  614. if err != nil {
  615. return nil, err
  616. }
  617. }
  618. if len(tmp) == 2 {
  619. flavor = tmp[1]
  620. } else {
  621. flavor = ""
  622. }
  623. return &KernelVersionInfo{
  624. Kernel: kernel,
  625. Major: major,
  626. Minor: minor,
  627. Flavor: flavor,
  628. }, nil
  629. }
  630. // FIXME: this is deprecated by CopyWithTar in archive.go
  631. func CopyDirectory(source, dest string) error {
  632. if output, err := exec.Command("cp", "-ra", source, dest).CombinedOutput(); err != nil {
  633. return fmt.Errorf("Error copy: %s (%s)", err, output)
  634. }
  635. return nil
  636. }
  637. type NopFlusher struct{}
  638. func (f *NopFlusher) Flush() {}
  639. type WriteFlusher struct {
  640. sync.Mutex
  641. w io.Writer
  642. flusher http.Flusher
  643. }
  644. func (wf *WriteFlusher) Write(b []byte) (n int, err error) {
  645. wf.Lock()
  646. defer wf.Unlock()
  647. n, err = wf.w.Write(b)
  648. wf.flusher.Flush()
  649. return n, err
  650. }
  651. // Flush the stream immediately.
  652. func (wf *WriteFlusher) Flush() {
  653. wf.Lock()
  654. defer wf.Unlock()
  655. wf.flusher.Flush()
  656. }
  657. func NewWriteFlusher(w io.Writer) *WriteFlusher {
  658. var flusher http.Flusher
  659. if f, ok := w.(http.Flusher); ok {
  660. flusher = f
  661. } else {
  662. flusher = &NopFlusher{}
  663. }
  664. return &WriteFlusher{w: w, flusher: flusher}
  665. }
  666. type JSONError struct {
  667. Code int `json:"code,omitempty"`
  668. Message string `json:"message,omitempty"`
  669. }
  670. type JSONMessage struct {
  671. Status string `json:"status,omitempty"`
  672. Progress string `json:"progress,omitempty"`
  673. ErrorMessage string `json:"error,omitempty"` //deprecated
  674. ID string `json:"id,omitempty"`
  675. From string `json:"from,omitempty"`
  676. Time int64 `json:"time,omitempty"`
  677. Error *JSONError `json:"errorDetail,omitempty"`
  678. }
  679. func (e *JSONError) Error() string {
  680. return e.Message
  681. }
  682. func NewHTTPRequestError(msg string, res *http.Response) error {
  683. return &JSONError{
  684. Message: msg,
  685. Code: res.StatusCode,
  686. }
  687. }
  688. func (jm *JSONMessage) Display(out io.Writer) error {
  689. if jm.Error != nil {
  690. if jm.Error.Code == 401 {
  691. return fmt.Errorf("Authentication is required.")
  692. }
  693. return jm.Error
  694. }
  695. fmt.Fprintf(out, "%c[2K\r", 27)
  696. if jm.Time != 0 {
  697. fmt.Fprintf(out, "[%s] ", time.Unix(jm.Time, 0))
  698. }
  699. if jm.ID != "" {
  700. fmt.Fprintf(out, "%s: ", jm.ID)
  701. }
  702. if jm.From != "" {
  703. fmt.Fprintf(out, "(from %s) ", jm.From)
  704. }
  705. if jm.Progress != "" {
  706. fmt.Fprintf(out, "%s %s\r", jm.Status, jm.Progress)
  707. } else {
  708. fmt.Fprintf(out, "%s\r\n", jm.Status)
  709. }
  710. return nil
  711. }
  712. func DisplayJSONMessagesStream(in io.Reader, out io.Writer) error {
  713. dec := json.NewDecoder(in)
  714. ids := make(map[string]int)
  715. diff := 0
  716. for {
  717. jm := JSONMessage{}
  718. if err := dec.Decode(&jm); err == io.EOF {
  719. break
  720. } else if err != nil {
  721. return err
  722. }
  723. if jm.Progress != "" && jm.ID != "" {
  724. line, ok := ids[jm.ID]
  725. if !ok {
  726. line = len(ids)
  727. ids[jm.ID] = line
  728. fmt.Fprintf(out, "\n")
  729. diff = 0
  730. } else {
  731. diff = len(ids) - line
  732. }
  733. fmt.Fprintf(out, "%c[%dA", 27, diff)
  734. }
  735. err := jm.Display(out)
  736. if jm.ID != "" {
  737. fmt.Fprintf(out, "%c[%dB", 27, diff)
  738. }
  739. if err != nil {
  740. return err
  741. }
  742. }
  743. return nil
  744. }
  745. type StreamFormatter struct {
  746. json bool
  747. used bool
  748. }
  749. func NewStreamFormatter(json bool) *StreamFormatter {
  750. return &StreamFormatter{json, false}
  751. }
  752. func (sf *StreamFormatter) FormatStatus(id, format string, a ...interface{}) []byte {
  753. sf.used = true
  754. str := fmt.Sprintf(format, a...)
  755. if sf.json {
  756. b, err := json.Marshal(&JSONMessage{ID: id, Status: str})
  757. if err != nil {
  758. return sf.FormatError(err)
  759. }
  760. return b
  761. }
  762. return []byte(str + "\r\n")
  763. }
  764. func (sf *StreamFormatter) FormatError(err error) []byte {
  765. sf.used = true
  766. if sf.json {
  767. jsonError, ok := err.(*JSONError)
  768. if !ok {
  769. jsonError = &JSONError{Message: err.Error()}
  770. }
  771. if b, err := json.Marshal(&JSONMessage{Error: jsonError, ErrorMessage: err.Error()}); err == nil {
  772. return b
  773. }
  774. return []byte("{\"error\":\"format error\"}")
  775. }
  776. return []byte("Error: " + err.Error() + "\r\n")
  777. }
  778. func (sf *StreamFormatter) FormatProgress(id, action, progress string) []byte {
  779. sf.used = true
  780. if sf.json {
  781. b, err := json.Marshal(&JSONMessage{Status: action, Progress: progress, ID: id})
  782. if err != nil {
  783. return nil
  784. }
  785. return b
  786. }
  787. return []byte(action + " " + progress + "\r")
  788. }
  789. func (sf *StreamFormatter) Used() bool {
  790. return sf.used
  791. }
  792. func IsURL(str string) bool {
  793. return strings.HasPrefix(str, "http://") || strings.HasPrefix(str, "https://")
  794. }
  795. func IsGIT(str string) bool {
  796. return strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "github.com/")
  797. }
  798. // GetResolvConf opens and read the content of /etc/resolv.conf.
  799. // It returns it as byte slice.
  800. func GetResolvConf() ([]byte, error) {
  801. resolv, err := ioutil.ReadFile("/etc/resolv.conf")
  802. if err != nil {
  803. Errorf("Error openning resolv.conf: %s", err)
  804. return nil, err
  805. }
  806. return resolv, nil
  807. }
  808. // CheckLocalDns looks into the /etc/resolv.conf,
  809. // it returns true if there is a local nameserver or if there is no nameserver.
  810. func CheckLocalDns(resolvConf []byte) bool {
  811. var parsedResolvConf = StripComments(resolvConf, []byte("#"))
  812. if !bytes.Contains(parsedResolvConf, []byte("nameserver")) {
  813. return true
  814. }
  815. for _, ip := range [][]byte{
  816. []byte("127.0.0.1"),
  817. []byte("127.0.1.1"),
  818. } {
  819. if bytes.Contains(parsedResolvConf, ip) {
  820. return true
  821. }
  822. }
  823. return false
  824. }
  825. // StripComments parses input into lines and strips away comments.
  826. func StripComments(input []byte, commentMarker []byte) []byte {
  827. lines := bytes.Split(input, []byte("\n"))
  828. var output []byte
  829. for _, currentLine := range lines {
  830. var commentIndex = bytes.Index(currentLine, commentMarker)
  831. if commentIndex == -1 {
  832. output = append(output, currentLine...)
  833. } else {
  834. output = append(output, currentLine[:commentIndex]...)
  835. }
  836. output = append(output, []byte("\n")...)
  837. }
  838. return output
  839. }
  840. // GetNameserversAsCIDR returns nameservers (if any) listed in
  841. // /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32")
  842. // This function's output is intended for net.ParseCIDR
  843. func GetNameserversAsCIDR(resolvConf []byte) []string {
  844. var parsedResolvConf = StripComments(resolvConf, []byte("#"))
  845. nameservers := []string{}
  846. re := regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`)
  847. for _, line := range bytes.Split(parsedResolvConf, []byte("\n")) {
  848. var ns = re.FindSubmatch(line)
  849. if len(ns) > 0 {
  850. nameservers = append(nameservers, string(ns[1])+"/32")
  851. }
  852. }
  853. return nameservers
  854. }
  855. func ParseHost(host string, port int, addr string) (string, error) {
  856. var proto string
  857. switch {
  858. case strings.HasPrefix(addr, "unix://"):
  859. return addr, nil
  860. case strings.HasPrefix(addr, "tcp://"):
  861. proto = "tcp"
  862. addr = strings.TrimPrefix(addr, "tcp://")
  863. default:
  864. if strings.Contains(addr, "://") {
  865. return "", fmt.Errorf("Invalid bind address protocol: %s", addr)
  866. }
  867. proto = "tcp"
  868. }
  869. if strings.Contains(addr, ":") {
  870. hostParts := strings.Split(addr, ":")
  871. if len(hostParts) != 2 {
  872. return "", fmt.Errorf("Invalid bind address format: %s", addr)
  873. }
  874. if hostParts[0] != "" {
  875. host = hostParts[0]
  876. }
  877. if p, err := strconv.Atoi(hostParts[1]); err == nil {
  878. port = p
  879. }
  880. } else {
  881. host = addr
  882. }
  883. return fmt.Sprintf("%s://%s:%d", proto, host, port), nil
  884. }
  885. func GetReleaseVersion() string {
  886. resp, err := http.Get("http://get.docker.io/latest")
  887. if err != nil {
  888. return ""
  889. }
  890. defer resp.Body.Close()
  891. if resp.ContentLength > 24 || resp.StatusCode != 200 {
  892. return ""
  893. }
  894. body, err := ioutil.ReadAll(resp.Body)
  895. if err != nil {
  896. return ""
  897. }
  898. return strings.TrimSpace(string(body))
  899. }
  900. // Get a repos name and returns the right reposName + tag
  901. // The tag can be confusing because of a port in a repository name.
  902. // Ex: localhost.localdomain:5000/samalba/hipache:latest
  903. func ParseRepositoryTag(repos string) (string, string) {
  904. n := strings.LastIndex(repos, ":")
  905. if n < 0 {
  906. return repos, ""
  907. }
  908. if tag := repos[n+1:]; !strings.Contains(tag, "/") {
  909. return repos[:n], tag
  910. }
  911. return repos, ""
  912. }
  913. type User struct {
  914. Uid string // user id
  915. Gid string // primary group id
  916. Username string
  917. Name string
  918. HomeDir string
  919. }
  920. // UserLookup check if the given username or uid is present in /etc/passwd
  921. // and returns the user struct.
  922. // If the username is not found, an error is returned.
  923. func UserLookup(uid string) (*User, error) {
  924. file, err := ioutil.ReadFile("/etc/passwd")
  925. if err != nil {
  926. return nil, err
  927. }
  928. for _, line := range strings.Split(string(file), "\n") {
  929. data := strings.Split(line, ":")
  930. if len(data) > 5 && (data[0] == uid || data[2] == uid) {
  931. return &User{
  932. Uid: data[2],
  933. Gid: data[3],
  934. Username: data[0],
  935. Name: data[4],
  936. HomeDir: data[5],
  937. }, nil
  938. }
  939. }
  940. return nil, fmt.Errorf("User not found in /etc/passwd")
  941. }
  942. type DependencyGraph struct {
  943. nodes map[string]*DependencyNode
  944. }
  945. type DependencyNode struct {
  946. id string
  947. deps map[*DependencyNode]bool
  948. }
  949. func NewDependencyGraph() DependencyGraph {
  950. return DependencyGraph{
  951. nodes: map[string]*DependencyNode{},
  952. }
  953. }
  954. func (graph *DependencyGraph) addNode(node *DependencyNode) string {
  955. if graph.nodes[node.id] == nil {
  956. graph.nodes[node.id] = node
  957. }
  958. return node.id
  959. }
  960. func (graph *DependencyGraph) NewNode(id string) string {
  961. if graph.nodes[id] != nil {
  962. return id
  963. }
  964. nd := &DependencyNode{
  965. id: id,
  966. deps: map[*DependencyNode]bool{},
  967. }
  968. graph.addNode(nd)
  969. return id
  970. }
  971. func (graph *DependencyGraph) AddDependency(node, to string) error {
  972. if graph.nodes[node] == nil {
  973. return fmt.Errorf("Node %s does not belong to this graph", node)
  974. }
  975. if graph.nodes[to] == nil {
  976. return fmt.Errorf("Node %s does not belong to this graph", to)
  977. }
  978. if node == to {
  979. return fmt.Errorf("Dependency loops are forbidden!")
  980. }
  981. graph.nodes[node].addDependency(graph.nodes[to])
  982. return nil
  983. }
  984. func (node *DependencyNode) addDependency(to *DependencyNode) bool {
  985. node.deps[to] = true
  986. return node.deps[to]
  987. }
  988. func (node *DependencyNode) Degree() int {
  989. return len(node.deps)
  990. }
  991. // The magic happens here ::
  992. func (graph *DependencyGraph) GenerateTraversalMap() ([][]string, error) {
  993. Debugf("Generating traversal map. Nodes: %d", len(graph.nodes))
  994. result := [][]string{}
  995. processed := map[*DependencyNode]bool{}
  996. // As long as we haven't processed all nodes...
  997. for len(processed) < len(graph.nodes) {
  998. // Use a temporary buffer for processed nodes, otherwise
  999. // nodes that depend on each other could end up in the same round.
  1000. tmp_processed := []*DependencyNode{}
  1001. for _, node := range graph.nodes {
  1002. // If the node has more dependencies than what we have cleared,
  1003. // it won't be valid for this round.
  1004. if node.Degree() > len(processed) {
  1005. continue
  1006. }
  1007. // If it's already processed, get to the next one
  1008. if processed[node] {
  1009. continue
  1010. }
  1011. // It's not been processed yet and has 0 deps. Add it!
  1012. // (this is a shortcut for what we're doing below)
  1013. if node.Degree() == 0 {
  1014. tmp_processed = append(tmp_processed, node)
  1015. continue
  1016. }
  1017. // If at least one dep hasn't been processed yet, we can't
  1018. // add it.
  1019. ok := true
  1020. for dep := range node.deps {
  1021. if !processed[dep] {
  1022. ok = false
  1023. break
  1024. }
  1025. }
  1026. // All deps have already been processed. Add it!
  1027. if ok {
  1028. tmp_processed = append(tmp_processed, node)
  1029. }
  1030. }
  1031. Debugf("Round %d: found %d available nodes", len(result), len(tmp_processed))
  1032. // If no progress has been made this round,
  1033. // that means we have circular dependencies.
  1034. if len(tmp_processed) == 0 {
  1035. return nil, fmt.Errorf("Could not find a solution to this dependency graph")
  1036. }
  1037. round := []string{}
  1038. for _, nd := range tmp_processed {
  1039. round = append(round, nd.id)
  1040. processed[nd] = true
  1041. }
  1042. result = append(result, round)
  1043. }
  1044. return result, nil
  1045. }
  1046. // An StatusError reports an unsuccessful exit by a command.
  1047. type StatusError struct {
  1048. Status int
  1049. }
  1050. func (e *StatusError) Error() string {
  1051. return fmt.Sprintf("Status: %d", e.Status)
  1052. }
  1053. func IsClosedError(err error) bool {
  1054. /* This comparison is ugly, but unfortunately, net.go doesn't export errClosing.
  1055. * See:
  1056. * http://golang.org/src/pkg/net/net.go
  1057. * https://code.google.com/p/go/issues/detail?id=4337
  1058. * https://groups.google.com/forum/#!msg/golang-nuts/0_aaCvBmOcM/SptmDyX1XJMJ
  1059. */
  1060. return strings.HasSuffix(err.Error(), "use of closed network connection")
  1061. }
  1062. func PartParser(template, data string) (map[string]string, error) {
  1063. // ip:public:private
  1064. templateParts := strings.Split(template, ":")
  1065. parts := strings.Split(data, ":")
  1066. if len(parts) != len(templateParts) {
  1067. return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
  1068. }
  1069. out := make(map[string]string, len(templateParts))
  1070. for i, t := range templateParts {
  1071. value := ""
  1072. if len(parts) > i {
  1073. value = parts[i]
  1074. }
  1075. out[t] = value
  1076. }
  1077. return out, nil
  1078. }