예제 #1
0
파일: daemon.go 프로젝트: crwloop/lxd
func (d *Daemon) SetupStorageDriver() error {
	vgName, err := d.ConfigValueGet("core.lvm_vg_name")
	if err != nil {
		return fmt.Errorf("Couldn't read config: %s", err)
	}
	if vgName != "" {
		d.Storage, err = newStorage(d, storageTypeLvm)
		if err != nil {
			shared.Logf("Could not initialize storage type LVM: %s - falling back to dir", err)
		} else {
			return nil
		}
	} else if d.BackingFs == "btrfs" {
		d.Storage, err = newStorage(d, storageTypeBtrfs)
		if err != nil {
			shared.Logf("Could not initialize storage type btrfs: %s - falling back to dir", err)
		} else {
			return nil
		}
	}

	d.Storage, err = newStorage(d, storageTypeDir)

	return err
}
예제 #2
0
func (s *storageLvm) ImageCreate(fingerprint string) error {
	finalName := shared.VarPath("images", fingerprint)

	lvpath, err := s.createThinLV(fingerprint)
	if err != nil {
		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
	}

	dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	tempLVMountPoint, err := ioutil.TempDir(shared.VarPath("images"), "tmp_lv_mnt")
	if err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(tempLVMountPoint); err != nil {
			s.log.Error("Deleting temporary LVM mount point", log.Ctx{"err": err})
		}
	}()

	var fstype string
	fstype, err = s.d.ConfigValueGet("storage.lvm_fstype")
	if err != nil {
		return fmt.Errorf("Error checking server config, err=%v", err)
	}

	if fstype == "" {
		fstype = "ext4"
	}

	err = s.tryMount(lvpath, tempLVMountPoint, fstype, 0, "discard")
	if err != nil {
		shared.Logf("Error mounting image LV for untarring: %v", err)
		return fmt.Errorf("Error mounting image LV: %v", err)

	}

	untarErr := untarImage(finalName, tempLVMountPoint)

	err = s.tryUnmount(tempLVMountPoint, 0)
	if err != nil {
		s.log.Warn("could not unmount LV. Will not remove",
			log.Ctx{"lvpath": lvpath, "mountpoint": tempLVMountPoint, "err": err})
		if untarErr == nil {
			return err
		}

		return fmt.Errorf(
			"Error unmounting '%s' during cleanup of error %v",
			tempLVMountPoint, untarErr)
	}

	return untarErr
}
예제 #3
0
func readSavedClientCAList(d *Daemon) {
	d.clientCerts = []x509.Certificate{}

	dbCerts, err := dbCertsGet(d.db)
	if err != nil {
		shared.Logf("Error reading certificates from database: %s", err)
		return
	}

	for _, dbCert := range dbCerts {
		certBlock, _ := pem.Decode([]byte(dbCert.Certificate))
		cert, err := x509.ParseCertificate(certBlock.Bytes)
		if err != nil {
			shared.Logf("Error reading certificate for %s: %s", dbCert.Name, err)
			continue
		}
		d.clientCerts = append(d.clientCerts, *cert)
	}
}
예제 #4
0
func (s *storageLvm) ImageCreate(fingerprint string) error {
	finalName := shared.VarPath("images", fingerprint)

	lvpath, err := s.createThinLV(fingerprint)
	if err != nil {
		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
	}

	dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	tempLVMountPoint, err := ioutil.TempDir(shared.VarPath("images"), "tmp_lv_mnt")
	if err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(tempLVMountPoint); err != nil {
			s.log.Error("Deleting temporary LVM mount point", log.Ctx{"err": err})
		}
	}()

	output, err := exec.Command(
		"mount",
		"-o", "discard",
		lvpath,
		tempLVMountPoint).CombinedOutput()

	if err != nil {
		shared.Logf("Error mounting image LV for untarring: '%s'", string(output))
		return fmt.Errorf("Error mounting image LV: %v", err)

	}

	untarErr := untarImage(finalName, tempLVMountPoint)

	output, err = exec.Command("umount", tempLVMountPoint).CombinedOutput()
	if err != nil {
		s.log.Warn("could not unmount LV. Will not remove",
			log.Ctx{"lvpath": lvpath, "mountpoint": tempLVMountPoint, "err": err})
		if untarErr == nil {
			return err
		}

		return fmt.Errorf(
			"Error unmounting '%s' during cleanup of error %v",
			tempLVMountPoint, untarErr)
	}

	return untarErr
}
예제 #5
0
파일: certificates.go 프로젝트: kostyll/lxd
func readSavedClientCAList(d *Daemon) {
	d.clientCerts = []x509.Certificate{}
	rows, err := dbQuery(d.db, "SELECT fingerprint, type, name, certificate FROM certificates")
	if err != nil {
		shared.Logf("Error reading certificates from database: %s\n", err)
		return
	}
	defer rows.Close()
	for rows.Next() {
		var fp string
		var t int
		var name string
		var cf []byte
		rows.Scan(&fp, &t, &name, &cf)
		cert_block, _ := pem.Decode(cf)
		cert, err := x509.ParseCertificate(cert_block.Bytes)
		if err != nil {
			shared.Logf("Error reading certificate for %s: %s\n", name, err)
			continue
		}
		d.clientCerts = append(d.clientCerts, *cert)
	}
}
예제 #6
0
파일: containers.go 프로젝트: kostyll/lxd
func containersShutdown(d *Daemon) error {
	q := fmt.Sprintf("SELECT name FROM containers WHERE type=?")
	inargs := []interface{}{cTypeRegular}
	var name string
	outfmt := []interface{}{name}

	result, err := dbQueryScan(d.db, q, inargs, outfmt)
	if err != nil {
		return err
	}

	var wg sync.WaitGroup

	for _, r := range result {
		container, err := newLxdContainer(string(r[0].(string)), d)
		if err != nil {
			return err
		}

		if container.c.State() != lxc.STOPPED {
			_, err = dbExec(d.db, "UPDATE containers SET power_state=1 WHERE name=?", container.name)
			if err != nil {
				return err
			}

			wg.Add(1)
			go func() {
				container.c.Shutdown(time.Second * 30)
				container.c.Stop()
				if err = deactivateStorage(d, container); err != nil {
					shared.Logf("Error deactivating storage after container stop: %v", err)
				}
				wg.Done()
			}()
		}
		wg.Wait()
	}

	return nil
}
예제 #7
0
func extractImage(hash string, name string, d *Daemon) error {
	/*
	 * We want to use archive/tar for this, but that doesn't appear
	 * to be working for us (see lxd/images.go)
	 */
	dpath := shared.VarPath("lxc", name)
	imagefile := shared.VarPath("images", hash)

	compression, _, err := detectCompression(imagefile)
	if err != nil {
		shared.Logf("Unkown compression type: %s", err)
		removeContainer(d, name)
		return err
	}

	args := []string{"-C", dpath, "--numeric-owner"}
	switch compression {
	case COMPRESSION_TAR:
		args = append(args, "-xf")
	case COMPRESSION_GZIP:
		args = append(args, "-zxf")
	case COMPRESSION_BZ2:
		args = append(args, "--jxf")
	case COMPRESSION_LZMA:
		args = append(args, "--lzma", "-xf")
	default:
		args = append(args, "-Jxf")
	}
	args = append(args, imagefile)

	output, err := exec.Command("tar", args...).Output()
	if err != nil {
		shared.Debugf("Untar of image: Output %s\nError %s\n", output, err)
		removeContainer(d, name)
		return err
	}

	return nil
}
예제 #8
0
파일: storage_lvm.go 프로젝트: rcj4747/lxd
func (s *storageLvm) ImageCreate(fingerprint string) error {
	finalName := shared.VarPath("images", fingerprint)

	poolname, err := s.d.ConfigValueGet("core.lvm_thinpool_name")
	if err != nil {
		return fmt.Errorf("Error checking server config, err=%v", err)
	}

	if poolname == "" {
		poolname, err = s.createDefaultThinPool()
		if err != nil {
			return fmt.Errorf("Error creating LVM thin pool: %v", err)
		}
		err = storageLVMSetThinPoolNameConfig(s.d, poolname)
		if err != nil {
			s.log.Error("Setting thin pool name", log.Ctx{"err": err})
			return fmt.Errorf("Error setting LVM thin pool config: %v", err)
		}
	}

	lvpath, err := s.createThinLV(fingerprint, poolname)
	if err != nil {
		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
	}

	dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	output, err := exec.Command(
		"mkfs.ext4",
		"-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0",
		lvpath).CombinedOutput()

	if err != nil {
		s.log.Error("mkfs.ext4", log.Ctx{"output": output})
		return fmt.Errorf("Error making filesystem on image LV: %v", err)
	}

	tempLVMountPoint, err := ioutil.TempDir(shared.VarPath("images"), "tmp_lv_mnt")
	if err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(tempLVMountPoint); err != nil {
			s.log.Error("Deleting temporary LVM mount point", log.Ctx{"err": err})
		}
	}()

	output, err = exec.Command(
		"mount",
		"-o", "discard",
		lvpath,
		tempLVMountPoint).CombinedOutput()

	if err != nil {
		shared.Logf("Error mounting image LV for untarring: '%s'", output)
		return fmt.Errorf("Error mounting image LV: %v", err)

	}

	untarErr := untarImage(finalName, tempLVMountPoint)

	output, err = exec.Command("umount", tempLVMountPoint).CombinedOutput()
	if err != nil {
		s.log.Warn("could not unmount LV. Will not remove",
			log.Ctx{"lvpath": lvpath, "mountpoint": tempLVMountPoint, "err": err})
		if untarErr == nil {
			return err
		}

		return fmt.Errorf(
			"Error unmounting '%s' during cleanup of error %v",
			tempLVMountPoint, untarErr)
	}

	return untarErr
}
예제 #9
0
파일: images.go 프로젝트: Ramzec/lxd
func createImageLV(d *Daemon, builddir string, fingerprint string, vgname string) error {
	imagefname := filepath.Join(builddir, fingerprint)
	poolname, poolnameIsSet, err := getServerConfigValue(d, "core.lvm_thinpool_name")
	if err != nil {
		return fmt.Errorf("Error checking server config: %v", err)
	}

	if !poolnameIsSet {
		poolname, err = shared.LVMCreateDefaultThinPool(vgname)
		if err != nil {
			return fmt.Errorf("Error creating LVM thin pool: %v", err)
		}
		err = setLVMThinPoolNameConfig(d, poolname)
		if err != nil {
			shared.Debugf("Error setting thin pool name: '%s'", err)
			return fmt.Errorf("Error setting LVM thin pool config: %v", err)
		}
	}

	lvpath, err := shared.LVMCreateThinLV(fingerprint, poolname, vgname)
	if err != nil {
		shared.Logf("Error from LVMCreateThinLV: '%v'", err)
		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
	}

	err = os.Symlink(lvpath, fmt.Sprintf("%s.lv", imagefname))
	if err != nil {
		return err
	}

	output, err := exec.Command("mkfs.ext4", "-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0", lvpath).CombinedOutput()
	if err != nil {
		shared.Logf("Error output from mkfs.ext4: '%s'", output)
		return fmt.Errorf("Error making filesystem on image LV: %v", err)
	}

	tempLVMountPoint, err := ioutil.TempDir(builddir, "tmp_lv_mnt")
	if err != nil {
		return err
	}

	output, err = exec.Command("mount", "-o", "discard", lvpath, tempLVMountPoint).CombinedOutput()
	if err != nil {
		shared.Logf("Error mounting image LV for untarring: '%s'", output)
		return fmt.Errorf("Error mounting image LV: %v", err)

	}

	untar_err := untarImage(imagefname, tempLVMountPoint)

	output, err = exec.Command("umount", tempLVMountPoint).CombinedOutput()
	if err != nil {
		shared.Logf("WARNING: could not unmount LV '%s' from '%s'. Will not remove. Error: %v", lvpath, tempLVMountPoint, err)
		if untar_err == nil {
			return err
		} else {
			return fmt.Errorf("Error unmounting '%s' during cleanup of error %v", tempLVMountPoint, untar_err)
		}
	}

	return untar_err
}
예제 #10
0
파일: daemon.go 프로젝트: Ramzec/lxd
// StartDaemon starts the shared daemon with the provided configuration.
func StartDaemon(listenAddr string) (*Daemon, error) {
	d := &Daemon{}

	d.lxcpath = shared.VarPath("lxc")
	err := os.MkdirAll(shared.VarPath("/"), 0755)
	if err != nil {
		return nil, err
	}
	err = os.MkdirAll(d.lxcpath, 0755)
	if err != nil {
		return nil, err
	}

	d.BackingFs, err = shared.GetFilesystem(d.lxcpath)
	if err != nil {
		shared.Debugf("Error detecting backing fs: %s\n", err)
	}

	certf, keyf, err := readMyCert()
	if err != nil {
		return nil, err
	}
	d.certf = certf
	d.keyf = keyf

	err = initDb(d)
	if err != nil {
		return nil, err
	}

	readSavedClientCAList(d)

	d.mux = mux.NewRouter()

	d.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		SyncResponse(true, []string{"/1.0"}).Render(w)
	})

	for _, c := range api10 {
		d.createCmd("1.0", c)
	}

	d.mux.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		shared.Debugf("sending top level 404: %s", r.URL)
		w.Header().Set("Content-Type", "application/json")
		NotFound.Render(w)
	})

	d.IdmapSet, err = shared.DefaultIdmapSet()
	if err != nil {
		shared.Logf("error reading idmap: %s", err.Error())
		shared.Logf("operations requiring idmap will not be available")
	} else {
		shared.Debugf("Default uid/gid map:")
		for _, lxcmap := range d.IdmapSet.ToLxcString() {
			shared.Debugf(" - " + lxcmap)
		}
	}

	tlsConfig, err := shared.GetTLSConfig(d.certf, d.keyf)
	if err != nil {
		return nil, err
	}

	listeners, err := activation.Listeners(false)
	if err != nil {
		return nil, err
	}

	var localSockets []net.Listener
	var remoteSockets []net.Listener

	if len(listeners) > 0 {
		shared.Debugf("LXD is socket activated.\n")

		for _, listener := range listeners {
			if _, err := os.Stat(listener.Addr().String()); err == nil {
				localSockets = append(localSockets, listener)
			} else {
				tlsListener := tls.NewListener(listener, tlsConfig)
				remoteSockets = append(remoteSockets, tlsListener)
			}
		}
	} else {
		shared.Debugf("LXD isn't socket activated.\n")

		localSocketPath := shared.VarPath("unix.socket")

		// If the socket exists, let's try to connect to it and see if there's
		// a lxd running.
		if _, err := os.Stat(localSocketPath); err == nil {
			c := &lxd.Config{Remotes: map[string]lxd.RemoteConfig{}}
			_, err := lxd.NewClient(c, "")
			if err != nil {
				shared.Debugf("Detected old but dead unix socket, deleting it...")
				// Connecting failed, so let's delete the socket and
				// listen on it ourselves.
				err = os.Remove(localSocketPath)
				if err != nil {
					return nil, err
				}
			}
		}

		unixAddr, err := net.ResolveUnixAddr("unix", localSocketPath)
		if err != nil {
			return nil, fmt.Errorf("cannot resolve unix socket address: %v", err)
		}

		unixl, err := net.ListenUnix("unix", unixAddr)
		if err != nil {
			return nil, fmt.Errorf("cannot listen on unix socket: %v", err)
		}

		if err := os.Chmod(localSocketPath, 0660); err != nil {
			return nil, err
		}

		gid, err := shared.GroupId(*group)
		if err != nil {
			return nil, err
		}

		if err := os.Chown(localSocketPath, os.Getuid(), gid); err != nil {
			return nil, err
		}

		localSockets = append(localSockets, unixl)

		if listenAddr != "" {
			tcpl, err := tls.Listen("tcp", listenAddr, tlsConfig)
			if err != nil {
				return nil, fmt.Errorf("cannot listen on unix socket: %v", err)
			}

			remoteSockets = append(remoteSockets, tcpl)
		}
	}

	d.localSockets = localSockets
	d.remoteSockets = remoteSockets
	d.devlxd, err = createAndBindDevLxd()
	if err != nil {
		return nil, err
	}

	containersRestart(d)
	containersWatch(d)

	d.tomb.Go(func() error {
		for _, socket := range d.localSockets {
			shared.Debugf(" - binding local socket: %s\n", socket.Addr())
			d.tomb.Go(func() error { return http.Serve(socket, d.mux) })
		}
		for _, socket := range d.remoteSockets {
			shared.Debugf(" - binding remote socket: %s\n", socket.Addr())
			d.tomb.Go(func() error { return http.Serve(socket, d.mux) })
		}

		d.tomb.Go(func() error {
			server := devLxdServer(d)
			return server.Serve(d.devlxd)
		})
		return nil
	})

	return d, nil
}
예제 #11
0
파일: devlxd_gccgo.go 프로젝트: max0d41/lxd
func createAndBindDevLxd() (*net.UnixListener, error) {
	shared.Logf("WARNING: devlxd not supported under gccgo")
	return nil, nil
}