<commit_before>package main

import (
	"appengine"
	"appengine/datastore"
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/hoisie/mustache"
	"net/http"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
)

func UserFetchHandler(w http.ResponseWriter, r *http.Request) {
	dir := path.Join(os.Getenv("PWD"), "templates")
	profile := path.Join(dir, "profile.html")
	layout := path.Join(dir, "profileLayout.html")
	vars := mux.Vars(r)
	c := appengine.NewContext(r)

	db := DB{c}
	match, _ := regexp.MatchString("^[0-9]+$", vars["user"])
	var err error
	var userMetaTemp interface{}
	var storedUserData interface{}
	var data string

	if match {
		userId, _ := strconv.ParseInt(vars["user"], 10, 64)
		userMetaTemp, err = db.GetUserMeta(userId)
		storedUserData, _ = db.GetUserData(userId)
	} else {
		temp := []StoredUserMeta{}
		q := datastore.NewQuery("UserMeta").Filter("VanityUrl =", strings.ToLower(vars["user"])).Limit(1)
		k, _ := q.GetAll(c, &temp)
		if len(temp) > 0 {
			userMetaTemp = temp[0]
			storedUserData, _ = db.GetUserData(k[0].IntID())
		} else {
			user404 := path.Join(dir, "user404.html")
			userData := map[string]string{"user": vars["user"]}
			data = mustache.RenderFileInLayout(user404, layout, userData)
			w.WriteHeader(http.StatusNotFound)
		}
	}

	if err == datastore.ErrNoSuchEntity {
		user404 := path.Join(dir, "user404.html")
		userData := map[string]string{"user": vars["user"]}
		data = mustache.RenderFileInLayout(user404, layout, userData)
		w.WriteHeader(http.StatusNotFound)
	} else if err != nil {
		fmt.Fprint(w, err.Error())
	} else if userMetaTemp != nil {

		userMeta := userMetaTemp.(StoredUserMeta)

		userData := map[string]interface{}{
			"username":    userMeta.Username,
			"description": userMeta.Description,
			"location":    userMeta.Location,
			"avatarUrl":   userMeta.AvatarUrl,
			"loops":       strconv.FormatInt(userMeta.Current.Loops, 10),
			"followers":   strconv.FormatInt(userMeta.Current.Followers, 10),
			"data":        storedUserData,
			"previous":    userMeta.Previous,
		}

		if userMeta.Background != "" {
			color := strings.SplitAfterN(userMeta.Background, "0x", 2)
			userData["profileBackground"] = color[1]
		} else {
			userData["profileBackground"] = "00BF8F"
		}

		data = mustache.RenderFileInLayout(profile, layout, userData)
	}

	fmt.Fprint(w, data)
}

func UserStoreHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	vineApi := VineRequest{c}
	db := DB{c}
	_, err := GetQueuedUser(r.FormValue("id"), c)
	data := make(map[string]bool)

	if err != datastore.ErrNoSuchEntity && err != nil {
	    c.Errorf("got UserStore err: %v", err)
	}

    user, apiErr := vineApi.GetUser(r.FormValue("id"))

	if err == datastore.ErrNoSuchEntity {

		if apiErr != nil {
			data["exists"] = false
			data["queued"] = false
		} else {
		    QueueUser(user.UserIdStr, c)
			data["exists"] = true
			data["queued"] = true
		}

		data["stored"] = false

	} else {
	    _, err := db.GetUserMeta(user.UserId)
	    if err == datastore.ErrNoSuchEntity {
	        data["stored"] = false
	    } else {
	        data["stored"] = true
	    }
		data["exists"] = true
		data["queued"] = false
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(data)
}

func AboutHandler(w http.ResponseWriter, r *http.Request) {
    dir := path.Join(os.Getenv("PWD"), "templates")
	aboutPage := path.Join(dir, "about.html")
	layout := path.Join(dir, "pageLayout.html")

	db := DB{appengine.NewContext(r)}
	totalUsers, _ := db.GetTotalUsers()
	stats := map[string]interface{}{"users": totalUsers}
	stats["lastUpdated"] = db.GetLastUpdated()
	data := mustache.RenderFileInLayout(aboutPage, layout, stats)

	fmt.Fprint(w, data)
}

func DiscoverHandler(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    vineApi := VineRequest{c}
    db := DB{c}
    var recentUsers []*VineUser
    var recentVerified []StoredUserMeta

    recent := datastore.NewQuery("Queue").Order("-Discovered").Limit(5).KeysOnly()
    k, _ := recent.GetAll(c, nil)
    for i, _ := range k {
        user, err := vineApi.GetUser(strconv.FormatInt(k[i].IntID(), 10))
        if err == nil {
            recentUsers = append(recentUsers, user)
        }
    }
    verified := datastore.NewQuery("UserMeta").Filter("Verified =", true).Limit(5).KeysOnly()
    k, _ = verified.GetAll(c, nil)
    for i , _ := range k {
        user, err := db.GetUserMeta(k[i].IntID())
        if err == nil {
           recentVerified = append(recentVerified, user.(StoredUserMeta))
        }
    }
    data := map[string]interface{}{"recentUsers": recentUsers, "recentVerified": recentVerified}
    dir := path.Join(os.Getenv("PWD"), "templates")
    discover := path.Join(dir, "discover.html")
    layout := path.Join(dir, "pageLayout.html")
    page := mustache.RenderFileInLayout(discover, layout, data)
    fmt.Fprint(w, page)
}

func TopHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	db := DB{c}

	dir := path.Join(os.Getenv("PWD"), "templates")
	top := path.Join(dir, "top.html")
	layout := path.Join(dir, "pageLayout.html")
	data := db.GetTop()
	data["LastUpdated"] = db.GetLastUpdated()
	page := mustache.RenderFileInLayout(top, layout, data)
	fmt.Fprint(w, page)
}

func RandomHandler(w http.ResponseWriter, r *http.Request) {
       c := appengine.NewContext(r)
       q := datastore.NewQuery("UserMeta").KeysOnly()
       keys, _ := q.GetAll(c, nil)

       keys = Shuffle(keys)
       var user QueuedUser
       c.Infof("first key %v", keys[0])
       key := datastore.NewKey(c, "Queue", "", keys[0].IntID(), nil)
       err := datastore.Get(c, key, &user)
       c.Errorf("got err %v", err)
       c.Infof("got user %v", user)
       http.Redirect(w, r, "/u/" + user.UserID, 301)
}

func DonateHandler(w http.ResponseWriter, r *http.Request) {
    dir := path.Join(os.Getenv("PWD"), "templates")
    donate := path.Join(dir, "donate.html")
    layout := path.Join(dir, "pageLayout.html")
    page := mustache.RenderFileInLayout(donate, layout, nil)
    fmt.Fprint(w, page)
}

func PopularFetchHandler(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    vineApi := VineRequest{c}

    users, err := vineApi.GetPopularUsers()
    for _, v := range users {
        if _, err := GetQueuedUser(v, c); err == datastore.ErrNoSuchEntity {
            QueueUser(v, c)
        }
    }
    fmt.Fprint(w, "queuing popular users: %v w/ err %v", users, err)
}

func CronFetchHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)

	q := datastore.NewQuery("Queue").KeysOnly()
	keys, _ := q.GetAll(c, nil)
	db := DB{c}

	for _, v := range keys {
		db.FetchUser(strconv.FormatInt(v.IntID(), 10))
	}

	c.Infof("Finished cron fetch")

	fmt.Fprint(w, "fetching users")
}

func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
    dir := path.Join(os.Getenv("PWD"), "templates")
    notFound := path.Join(dir, "404.html")
    layout := path.Join(dir, "pageLayout.html")
    data := map[string]string{"url": r.RequestURI}
    page := mustache.RenderFileInLayout(notFound, layout, data)
    w.WriteHeader(404)
    fmt.Fprint(w, page)
}<commit_msg>Increased some server logging.<commit_after>package main

import (
	"appengine"
	"appengine/datastore"
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/hoisie/mustache"
	"net/http"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
)

func UserFetchHandler(w http.ResponseWriter, r *http.Request) {
	dir := path.Join(os.Getenv("PWD"), "templates")
	profile := path.Join(dir, "profile.html")
	layout := path.Join(dir, "profileLayout.html")
	vars := mux.Vars(r)
	c := appengine.NewContext(r)

	db := DB{c}
	match, _ := regexp.MatchString("^[0-9]+$", vars["user"])
	var err error
	var userMetaTemp interface{}
	var storedUserData interface{}
	var data string

	if match {
		userId, _ := strconv.ParseInt(vars["user"], 10, 64)
		userMetaTemp, err = db.GetUserMeta(userId)
		storedUserData, _ = db.GetUserData(userId)
	} else {
		temp := []StoredUserMeta{}
		q := datastore.NewQuery("UserMeta").Filter("VanityUrl =", strings.ToLower(vars["user"])).Limit(1)
		k, _ := q.GetAll(c, &temp)
		if len(temp) > 0 {
			userMetaTemp = temp[0]
			storedUserData, _ = db.GetUserData(k[0].IntID())
		} else {
			user404 := path.Join(dir, "user404.html")
			userData := map[string]string{"user": vars["user"]}
			data = mustache.RenderFileInLayout(user404, layout, userData)
			w.WriteHeader(http.StatusNotFound)
		}
	}

	if err == datastore.ErrNoSuchEntity {
		user404 := path.Join(dir, "user404.html")
		userData := map[string]string{"user": vars["user"]}
		data = mustache.RenderFileInLayout(user404, layout, userData)
		w.WriteHeader(http.StatusNotFound)
	} else if err != nil {
		fmt.Fprint(w, err.Error())
	} else if userMetaTemp != nil {

		userMeta := userMetaTemp.(StoredUserMeta)

		userData := map[string]interface{}{
			"username":    userMeta.Username,
			"description": userMeta.Description,
			"location":    userMeta.Location,
			"avatarUrl":   userMeta.AvatarUrl,
			"loops":       strconv.FormatInt(userMeta.Current.Loops, 10),
			"followers":   strconv.FormatInt(userMeta.Current.Followers, 10),
			"data":        storedUserData,
			"previous":    userMeta.Previous,
		}

		if userMeta.Background != "" {
			color := strings.SplitAfterN(userMeta.Background, "0x", 2)
			userData["profileBackground"] = color[1]
		} else {
			userData["profileBackground"] = "00BF8F"
		}

		data = mustache.RenderFileInLayout(profile, layout, userData)
	}

	fmt.Fprint(w, data)
}

func UserStoreHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	vineApi := VineRequest{c}
	db := DB{c}
	_, err := GetQueuedUser(r.FormValue("id"), c)
	data := make(map[string]bool)

	if err != datastore.ErrNoSuchEntity && err != nil {
	    c.Errorf("got UserStore err: %v", err)
	}

    user, apiErr := vineApi.GetUser(r.FormValue("id"))

	if err == datastore.ErrNoSuchEntity {

		if apiErr != nil {
			data["exists"] = false
			data["queued"] = false
		} else {
		    QueueUser(user.UserIdStr, c)
			data["exists"] = true
			data["queued"] = true
		}

		data["stored"] = false

	} else {
	    _, err := db.GetUserMeta(user.UserId)
	    if err == datastore.ErrNoSuchEntity {
	        data["stored"] = false
	    } else {
	        data["stored"] = true
	    }
		data["exists"] = true
		data["queued"] = false
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(data)
}

func AboutHandler(w http.ResponseWriter, r *http.Request) {
    dir := path.Join(os.Getenv("PWD"), "templates")
	aboutPage := path.Join(dir, "about.html")
	layout := path.Join(dir, "pageLayout.html")

	db := DB{appengine.NewContext(r)}
	totalUsers, _ := db.GetTotalUsers()
	stats := map[string]interface{}{"users": totalUsers}
	stats["lastUpdated"] = db.GetLastUpdated()
	data := mustache.RenderFileInLayout(aboutPage, layout, stats)

	fmt.Fprint(w, data)
}

func DiscoverHandler(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    vineApi := VineRequest{c}
    db := DB{c}
    var recentUsers []*VineUser
    var recentVerified []StoredUserMeta

    recent := datastore.NewQuery("Queue").Order("-Discovered").Limit(5).KeysOnly()
    k, _ := recent.GetAll(c, nil)
    for i, _ := range k {
        user, err := vineApi.GetUser(strconv.FormatInt(k[i].IntID(), 10))
        if err == nil {
            recentUsers = append(recentUsers, user)
        }
    }
    verified := datastore.NewQuery("UserMeta").Filter("Verified =", true).Limit(5).KeysOnly()
    k, _ = verified.GetAll(c, nil)
    for i , _ := range k {
        user, err := db.GetUserMeta(k[i].IntID())
        if err == nil {
           recentVerified = append(recentVerified, user.(StoredUserMeta))
        }
    }
    data := map[string]interface{}{"recentUsers": recentUsers, "recentVerified": recentVerified}
    dir := path.Join(os.Getenv("PWD"), "templates")
    discover := path.Join(dir, "discover.html")
    layout := path.Join(dir, "pageLayout.html")
    page := mustache.RenderFileInLayout(discover, layout, data)
    fmt.Fprint(w, page)
}

func TopHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	db := DB{c}

	dir := path.Join(os.Getenv("PWD"), "templates")
	top := path.Join(dir, "top.html")
	layout := path.Join(dir, "pageLayout.html")
	data := db.GetTop()
	data["LastUpdated"] = db.GetLastUpdated()
	page := mustache.RenderFileInLayout(top, layout, data)
	fmt.Fprint(w, page)
}

func RandomHandler(w http.ResponseWriter, r *http.Request) {
       c := appengine.NewContext(r)
       q := datastore.NewQuery("UserMeta").KeysOnly()
       keys, _ := q.GetAll(c, nil)

       keys = Shuffle(keys)
       var user QueuedUser
       key := datastore.NewKey(c, "Queue", "", keys[0].IntID(), nil)
       err := datastore.Get(c, key, &user)
       if err != nil {
        c.Errorf("got err %v", err)
       } else {
        c.Infof("got user %v", user)
       }
       http.Redirect(w, r, "/u/" + user.UserID, 301)
}

func DonateHandler(w http.ResponseWriter, r *http.Request) {
    dir := path.Join(os.Getenv("PWD"), "templates")
    donate := path.Join(dir, "donate.html")
    layout := path.Join(dir, "pageLayout.html")
    page := mustache.RenderFileInLayout(donate, layout, nil)
    fmt.Fprint(w, page)
}

func PopularFetchHandler(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    vineApi := VineRequest{c}

    users, err := vineApi.GetPopularUsers()
    for _, v := range users {
        if _, err := GetQueuedUser(v, c); err == datastore.ErrNoSuchEntity {
            QueueUser(v, c)
        }
    }
    fmt.Fprint(w, "queuing popular users: %v w/ err %v", users, err)
    c.Infof("queueing popular users: %v w/ err %v", users, err)
}

func CronFetchHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)

	q := datastore.NewQuery("Queue").KeysOnly()
	keys, _ := q.GetAll(c, nil)
	db := DB{c}

	for _, v := range keys {
		db.FetchUser(strconv.FormatInt(v.IntID(), 10))
	}

	c.Infof("Finished cron fetch")

	fmt.Fprint(w, "fetching users")
}

func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
    dir := path.Join(os.Getenv("PWD"), "templates")
    notFound := path.Join(dir, "404.html")
    layout := path.Join(dir, "pageLayout.html")
    data := map[string]string{"url": r.RequestURI}
    page := mustache.RenderFileInLayout(notFound, layout, data)
    w.WriteHeader(404)
    fmt.Fprint(w, page)
}<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package azure_dd

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	utilfeature "k8s.io/apiserver/pkg/util/feature"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/azure"
	"k8s.io/kubernetes/pkg/features"
	kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
	"k8s.io/kubernetes/pkg/volume"
	"k8s.io/kubernetes/pkg/volume/util"
)

type azureDiskProvisioner struct {
	plugin  *azureDataDiskPlugin
	options volume.VolumeOptions
}

type azureDiskDeleter struct {
	*dataDisk
	spec   *volume.Spec
	plugin *azureDataDiskPlugin
}

var _ volume.Provisioner = &azureDiskProvisioner{}
var _ volume.Deleter = &azureDiskDeleter{}

func (d *azureDiskDeleter) GetPath() string {
	return getPath(d.podUID, d.dataDisk.diskName, d.plugin.host)
}

func (d *azureDiskDeleter) Delete() error {
	volumeSource, _, err := getVolumeSource(d.spec)
	if err != nil {
		return err
	}

	diskController, err := getDiskController(d.plugin.host)
	if err != nil {
		return err
	}

	managed := (*volumeSource.Kind == v1.AzureManagedDisk)

	if managed {
		return diskController.DeleteManagedDisk(volumeSource.DataDiskURI)
	}

	return diskController.DeleteBlobDisk(volumeSource.DataDiskURI)
}

// parseZoned parsed 'zoned' for storage class. If zoned is not specified (empty string),
// then it defaults to true for managed disks.
func parseZoned(zonedString string, kind v1.AzureDataDiskKind) (bool, error) {
	if zonedString == "" {
		return kind == v1.AzureManagedDisk, nil
	}

	zoned, err := strconv.ParseBool(zonedString)
	if err != nil {
		return false, fmt.Errorf("failed to parse 'zoned': %v", err)
	}

	if zoned && kind != v1.AzureManagedDisk {
		return false, fmt.Errorf("zoned is only supported by managed disks")
	}

	return zoned, nil
}

func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
	if !util.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) {
		return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes())
	}
	supportedModes := p.plugin.GetAccessModes()

	// perform static validation first
	if p.options.PVC.Spec.Selector != nil {
		return nil, fmt.Errorf("azureDisk - claim.Spec.Selector is not supported for dynamic provisioning on Azure disk")
	}

	if len(p.options.PVC.Spec.AccessModes) > 1 {
		return nil, fmt.Errorf("AzureDisk - multiple access modes are not supported on AzureDisk plugin")
	}

	if len(p.options.PVC.Spec.AccessModes) == 1 {
		if p.options.PVC.Spec.AccessModes[0] != supportedModes[0] {
			return nil, fmt.Errorf("AzureDisk - mode %s is not supported by AzureDisk plugin (supported mode is %s)", p.options.PVC.Spec.AccessModes[0], supportedModes)
		}
	}

	var (
		location, account          string
		storageAccountType, fsType string
		cachingMode                v1.AzureDataDiskCachingMode
		strKind                    string
		err                        error
		resourceGroup              string

		zoned                    bool
		zonePresent              bool
		zonesPresent             bool
		strZoned                 string
		availabilityZone         string
		availabilityZones        sets.String
		selectedAvailabilityZone string
	)
	// maxLength = 79 - (4 for ".vhd") = 75
	name := util.GenerateVolumeName(p.options.ClusterName, p.options.PVName, 75)
	capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
	requestGiB, err := util.RoundUpToGiBInt(capacity)
	if err != nil {
		return nil, err
	}

	for k, v := range p.options.Parameters {
		switch strings.ToLower(k) {
		case "skuname":
			storageAccountType = v
		case "location":
			location = v
		case "storageaccount":
			account = v
		case "storageaccounttype":
			storageAccountType = v
		case "kind":
			strKind = v
		case "cachingmode":
			cachingMode = v1.AzureDataDiskCachingMode(v)
		case volume.VolumeParameterFSType:
			fsType = strings.ToLower(v)
		case "resourcegroup":
			resourceGroup = v
		case "zone":
			zonePresent = true
			availabilityZone = v
		case "zones":
			zonesPresent = true
			availabilityZones, err = util.ZonesToSet(v)
			if err != nil {
				return nil, fmt.Errorf("error parsing zones %s, must be strings separated by commas: %v", v, err)
			}
		case "zoned":
			strZoned = v
		default:
			return nil, fmt.Errorf("AzureDisk - invalid option %s in storage class", k)
		}
	}

	// normalize values
	skuName, err := normalizeStorageAccountType(storageAccountType)
	if err != nil {
		return nil, err
	}

	kind, err := normalizeKind(strFirstLetterToUpper(strKind))
	if err != nil {
		return nil, err
	}

	zoned, err = parseZoned(strZoned, kind)
	if err != nil {
		return nil, err
	}

	if kind != v1.AzureManagedDisk {
		if resourceGroup != "" {
			return nil, errors.New("StorageClass option 'resourceGroup' can be used only for managed disks")
		}

		if zoned {
			return nil, errors.New("StorageClass option 'zoned' parameter is only supported for managed disks")
		}
	}

	if !zoned && (zonePresent || zonesPresent || len(allowedTopologies) > 0) {
		return nil, fmt.Errorf("zone, zones and allowedTopologies StorageClass parameters must be used together with zoned parameter")
	}

	if cachingMode, err = normalizeCachingMode(cachingMode); err != nil {
		return nil, err
	}

	diskController, err := getDiskController(p.plugin.host)
	if err != nil {
		return nil, err
	}

	// Select zone for managed disks based on zone, zones and allowedTopologies.
	if zoned {
		activeZones, err := diskController.GetActiveZones()
		if err != nil {
			return nil, fmt.Errorf("error querying active zones: %v", err)
		}

		selectedAvailabilityZone, err = util.SelectZoneForVolume(zonePresent, zonesPresent, availabilityZone, availabilityZones, activeZones, selectedNode, allowedTopologies, p.options.PVC.Name)
		if err != nil {
			return nil, err
		}
	}

	// create disk
	diskURI := ""
	labels := map[string]string{}
	if kind == v1.AzureManagedDisk {
		tags := make(map[string]string)
		if p.options.CloudTags != nil {
			tags = *(p.options.CloudTags)
		}

		volumeOptions := &azure.ManagedDiskOptions{
			DiskName:           name,
			StorageAccountType: skuName,
			ResourceGroup:      resourceGroup,
			PVCName:            p.options.PVC.Name,
			SizeGB:             requestGiB,
			Tags:               tags,
			AvailabilityZone:   selectedAvailabilityZone,
		}
		diskURI, err = diskController.CreateManagedDisk(volumeOptions)
		if err != nil {
			return nil, err
		}
		labels, err = diskController.GetAzureDiskLabels(diskURI)
		if err != nil {
			return nil, err
		}
	} else {
		if kind == v1.AzureDedicatedBlobDisk {
			_, diskURI, _, err = diskController.CreateVolume(name, account, storageAccountType, location, requestGiB)
			if err != nil {
				return nil, err
			}
		} else {
			diskURI, err = diskController.CreateBlobDisk(name, skuName, requestGiB)
			if err != nil {
				return nil, err
			}
		}
	}

	var volumeMode *v1.PersistentVolumeMode
	if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
		volumeMode = p.options.PVC.Spec.VolumeMode
		if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
			// Block volumes should not have any FSType
			fsType = ""
		}
	}

	pv := &v1.PersistentVolume{
		ObjectMeta: metav1.ObjectMeta{
			Name:   p.options.PVName,
			Labels: labels,
			Annotations: map[string]string{
				"volumehelper.VolumeDynamicallyCreatedByKey": "azure-disk-dynamic-provisioner",
			},
		},
		Spec: v1.PersistentVolumeSpec{
			PersistentVolumeReclaimPolicy: p.options.PersistentVolumeReclaimPolicy,
			AccessModes:                   supportedModes,
			Capacity: v1.ResourceList{
				v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", requestGiB)),
			},
			VolumeMode: volumeMode,
			PersistentVolumeSource: v1.PersistentVolumeSource{
				AzureDisk: &v1.AzureDiskVolumeSource{
					CachingMode: &cachingMode,
					DiskName:    name,
					DataDiskURI: diskURI,
					Kind:        &kind,
					FSType:      &fsType,
				},
			},
			MountOptions: p.options.MountOptions,
		},
	}

	if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
		nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0)

		if zoned {
			// Set node affinity labels based on availability zone labels.
			requirements := make([]v1.NodeSelectorRequirement, 0)
			for k, v := range labels {
				requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
			}

			nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
				MatchExpressions: requirements,
			})
		} else {
			// Set node affinity labels based on fault domains.
			// This is required because unzoned AzureDisk can't be attached to zoned nodes.
			// There are at most 3 fault domains available in each region.
			// Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability.
			for i := 0; i < 3; i++ {
				requirements := []v1.NodeSelectorRequirement{
					{
						Key:      kubeletapis.LabelZoneRegion,
						Operator: v1.NodeSelectorOpIn,
						Values:   []string{diskController.GetLocation()},
					},
					{
						Key:      kubeletapis.LabelZoneFailureDomain,
						Operator: v1.NodeSelectorOpIn,
						Values:   []string{strconv.Itoa(i)},
					},
				}
				nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
					MatchExpressions: requirements,
				})
			}
		}

		pv.Spec.NodeAffinity = &v1.VolumeNodeAffinity{
			Required: &v1.NodeSelector{
				NodeSelectorTerms: nodeSelectorTerms,
			},
		}
	}

	return pv, nil
}
<commit_msg>Only set nodeSelectorTerms when there are zoned nodes<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package azure_dd

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	utilfeature "k8s.io/apiserver/pkg/util/feature"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/azure"
	"k8s.io/kubernetes/pkg/features"
	kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
	"k8s.io/kubernetes/pkg/volume"
	"k8s.io/kubernetes/pkg/volume/util"
)

type azureDiskProvisioner struct {
	plugin  *azureDataDiskPlugin
	options volume.VolumeOptions
}

type azureDiskDeleter struct {
	*dataDisk
	spec   *volume.Spec
	plugin *azureDataDiskPlugin
}

var _ volume.Provisioner = &azureDiskProvisioner{}
var _ volume.Deleter = &azureDiskDeleter{}

func (d *azureDiskDeleter) GetPath() string {
	return getPath(d.podUID, d.dataDisk.diskName, d.plugin.host)
}

func (d *azureDiskDeleter) Delete() error {
	volumeSource, _, err := getVolumeSource(d.spec)
	if err != nil {
		return err
	}

	diskController, err := getDiskController(d.plugin.host)
	if err != nil {
		return err
	}

	managed := (*volumeSource.Kind == v1.AzureManagedDisk)

	if managed {
		return diskController.DeleteManagedDisk(volumeSource.DataDiskURI)
	}

	return diskController.DeleteBlobDisk(volumeSource.DataDiskURI)
}

// parseZoned parsed 'zoned' for storage class. If zoned is not specified (empty string),
// then it defaults to true for managed disks.
func parseZoned(zonedString string, kind v1.AzureDataDiskKind) (bool, error) {
	if zonedString == "" {
		return kind == v1.AzureManagedDisk, nil
	}

	zoned, err := strconv.ParseBool(zonedString)
	if err != nil {
		return false, fmt.Errorf("failed to parse 'zoned': %v", err)
	}

	if zoned && kind != v1.AzureManagedDisk {
		return false, fmt.Errorf("zoned is only supported by managed disks")
	}

	return zoned, nil
}

func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
	if !util.AccessModesContainedInAll(p.plugin.GetAccessModes(), p.options.PVC.Spec.AccessModes) {
		return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", p.options.PVC.Spec.AccessModes, p.plugin.GetAccessModes())
	}
	supportedModes := p.plugin.GetAccessModes()

	// perform static validation first
	if p.options.PVC.Spec.Selector != nil {
		return nil, fmt.Errorf("azureDisk - claim.Spec.Selector is not supported for dynamic provisioning on Azure disk")
	}

	if len(p.options.PVC.Spec.AccessModes) > 1 {
		return nil, fmt.Errorf("AzureDisk - multiple access modes are not supported on AzureDisk plugin")
	}

	if len(p.options.PVC.Spec.AccessModes) == 1 {
		if p.options.PVC.Spec.AccessModes[0] != supportedModes[0] {
			return nil, fmt.Errorf("AzureDisk - mode %s is not supported by AzureDisk plugin (supported mode is %s)", p.options.PVC.Spec.AccessModes[0], supportedModes)
		}
	}

	var (
		location, account          string
		storageAccountType, fsType string
		cachingMode                v1.AzureDataDiskCachingMode
		strKind                    string
		err                        error
		resourceGroup              string

		zoned                    bool
		zonePresent              bool
		zonesPresent             bool
		strZoned                 string
		availabilityZone         string
		availabilityZones        sets.String
		selectedAvailabilityZone string
	)
	// maxLength = 79 - (4 for ".vhd") = 75
	name := util.GenerateVolumeName(p.options.ClusterName, p.options.PVName, 75)
	capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
	requestGiB, err := util.RoundUpToGiBInt(capacity)
	if err != nil {
		return nil, err
	}

	for k, v := range p.options.Parameters {
		switch strings.ToLower(k) {
		case "skuname":
			storageAccountType = v
		case "location":
			location = v
		case "storageaccount":
			account = v
		case "storageaccounttype":
			storageAccountType = v
		case "kind":
			strKind = v
		case "cachingmode":
			cachingMode = v1.AzureDataDiskCachingMode(v)
		case volume.VolumeParameterFSType:
			fsType = strings.ToLower(v)
		case "resourcegroup":
			resourceGroup = v
		case "zone":
			zonePresent = true
			availabilityZone = v
		case "zones":
			zonesPresent = true
			availabilityZones, err = util.ZonesToSet(v)
			if err != nil {
				return nil, fmt.Errorf("error parsing zones %s, must be strings separated by commas: %v", v, err)
			}
		case "zoned":
			strZoned = v
		default:
			return nil, fmt.Errorf("AzureDisk - invalid option %s in storage class", k)
		}
	}

	// normalize values
	skuName, err := normalizeStorageAccountType(storageAccountType)
	if err != nil {
		return nil, err
	}

	kind, err := normalizeKind(strFirstLetterToUpper(strKind))
	if err != nil {
		return nil, err
	}

	zoned, err = parseZoned(strZoned, kind)
	if err != nil {
		return nil, err
	}

	if kind != v1.AzureManagedDisk {
		if resourceGroup != "" {
			return nil, errors.New("StorageClass option 'resourceGroup' can be used only for managed disks")
		}

		if zoned {
			return nil, errors.New("StorageClass option 'zoned' parameter is only supported for managed disks")
		}
	}

	if !zoned && (zonePresent || zonesPresent || len(allowedTopologies) > 0) {
		return nil, fmt.Errorf("zone, zones and allowedTopologies StorageClass parameters must be used together with zoned parameter")
	}

	if cachingMode, err = normalizeCachingMode(cachingMode); err != nil {
		return nil, err
	}

	diskController, err := getDiskController(p.plugin.host)
	if err != nil {
		return nil, err
	}

	// Select zone for managed disks based on zone, zones and allowedTopologies.
	if zoned {
		activeZones, err := diskController.GetActiveZones()
		if err != nil {
			return nil, fmt.Errorf("error querying active zones: %v", err)
		}

		selectedAvailabilityZone, err = util.SelectZoneForVolume(zonePresent, zonesPresent, availabilityZone, availabilityZones, activeZones, selectedNode, allowedTopologies, p.options.PVC.Name)
		if err != nil {
			return nil, err
		}
	}

	// create disk
	diskURI := ""
	labels := map[string]string{}
	if kind == v1.AzureManagedDisk {
		tags := make(map[string]string)
		if p.options.CloudTags != nil {
			tags = *(p.options.CloudTags)
		}

		volumeOptions := &azure.ManagedDiskOptions{
			DiskName:           name,
			StorageAccountType: skuName,
			ResourceGroup:      resourceGroup,
			PVCName:            p.options.PVC.Name,
			SizeGB:             requestGiB,
			Tags:               tags,
			AvailabilityZone:   selectedAvailabilityZone,
		}
		diskURI, err = diskController.CreateManagedDisk(volumeOptions)
		if err != nil {
			return nil, err
		}
		labels, err = diskController.GetAzureDiskLabels(diskURI)
		if err != nil {
			return nil, err
		}
	} else {
		if kind == v1.AzureDedicatedBlobDisk {
			_, diskURI, _, err = diskController.CreateVolume(name, account, storageAccountType, location, requestGiB)
			if err != nil {
				return nil, err
			}
		} else {
			diskURI, err = diskController.CreateBlobDisk(name, skuName, requestGiB)
			if err != nil {
				return nil, err
			}
		}
	}

	var volumeMode *v1.PersistentVolumeMode
	if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
		volumeMode = p.options.PVC.Spec.VolumeMode
		if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
			// Block volumes should not have any FSType
			fsType = ""
		}
	}

	pv := &v1.PersistentVolume{
		ObjectMeta: metav1.ObjectMeta{
			Name:   p.options.PVName,
			Labels: labels,
			Annotations: map[string]string{
				"volumehelper.VolumeDynamicallyCreatedByKey": "azure-disk-dynamic-provisioner",
			},
		},
		Spec: v1.PersistentVolumeSpec{
			PersistentVolumeReclaimPolicy: p.options.PersistentVolumeReclaimPolicy,
			AccessModes:                   supportedModes,
			Capacity: v1.ResourceList{
				v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", requestGiB)),
			},
			VolumeMode: volumeMode,
			PersistentVolumeSource: v1.PersistentVolumeSource{
				AzureDisk: &v1.AzureDiskVolumeSource{
					CachingMode: &cachingMode,
					DiskName:    name,
					DataDiskURI: diskURI,
					Kind:        &kind,
					FSType:      &fsType,
				},
			},
			MountOptions: p.options.MountOptions,
		},
	}

	if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
		nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0)

		if zoned {
			// Set node affinity labels based on availability zone labels.
			if len(labels) > 0 {
				requirements := make([]v1.NodeSelectorRequirement, 0)
				for k, v := range labels {
					requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
				}

				nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
					MatchExpressions: requirements,
				})
			}
		} else {
			// Set node affinity labels based on fault domains.
			// This is required because unzoned AzureDisk can't be attached to zoned nodes.
			// There are at most 3 fault domains available in each region.
			// Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability.
			for i := 0; i < 3; i++ {
				requirements := []v1.NodeSelectorRequirement{
					{
						Key:      kubeletapis.LabelZoneRegion,
						Operator: v1.NodeSelectorOpIn,
						Values:   []string{diskController.GetLocation()},
					},
					{
						Key:      kubeletapis.LabelZoneFailureDomain,
						Operator: v1.NodeSelectorOpIn,
						Values:   []string{strconv.Itoa(i)},
					},
				}
				nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
					MatchExpressions: requirements,
				})
			}
		}

		if len(nodeSelectorTerms) > 0 {
			pv.Spec.NodeAffinity = &v1.VolumeNodeAffinity{
				Required: &v1.NodeSelector{
					NodeSelectorTerms: nodeSelectorTerms,
				},
			}
		}
	}

	return pv, nil
}
<|endoftext|>


<commit_before>package backend

// InitPrometheus : Set some channels to notify other theads when using Prometheus
import (
	"github.com/prometheus/client_golang/prometheus"
)

// InitPrometheus : initialize prometheus
func (backend *Config) InitPrometheus(channel *chan bool, doneChannel *chan bool, promMetrics *chan Point) error {
	backend.channel = channel
	backend.doneChannel = doneChannel
	backend.promMetrics = promMetrics
	return nil
}

// Describe : Implementation of Prometheus Collector.Describe
func (backend *Config) Describe(ch chan<- *prometheus.Desc) {
	prometheus.NewGauge(prometheus.GaugeOpts{Name: "Dummy", Help: "Dummy"}).Describe(ch)
}

// Collect : Implementation of Prometheus Collector.Collect
func (backend *Config) Collect(ch chan<- prometheus.Metric) {

	stdlog.Println("Requested Metrics!")

	*backend.channel <- true

	for {
		select {
		case point := <-*backend.promMetrics:
			tags := point.GetTags(backend.NoArray, ",")
			labelNames := make([]string, len(tags))
			labelValues := make([]string, len(tags))
			i := 0
			for key, value := range tags {
				labelNames[i] = key
				labelValues[i] = value
				i++
			}
			key := point.ObjectType + "_" + point.Group + "_" + point.Counter + "_" + point.Rollup
			desc := prometheus.NewDesc(key, "vSphere collected metric", labelNames, nil)
			metric, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(point.Value), labelValues...)
			if err != nil {
				errlog.Println("E! Error creating prometheus metric")
			}
			ch <- metric
		case <-*backend.doneChannel:
			return
		}
	}
}
<commit_msg>remove type from metric name<commit_after>package backend

// InitPrometheus : Set some channels to notify other theads when using Prometheus
import (
	"github.com/prometheus/client_golang/prometheus"
)

// InitPrometheus : initialize prometheus
func (backend *Config) InitPrometheus(channel *chan bool, doneChannel *chan bool, promMetrics *chan Point) error {
	backend.channel = channel
	backend.doneChannel = doneChannel
	backend.promMetrics = promMetrics
	return nil
}

// Describe : Implementation of Prometheus Collector.Describe
func (backend *Config) Describe(ch chan<- *prometheus.Desc) {
	prometheus.NewGauge(prometheus.GaugeOpts{Name: "Dummy", Help: "Dummy"}).Describe(ch)
}

// Collect : Implementation of Prometheus Collector.Collect
func (backend *Config) Collect(ch chan<- prometheus.Metric) {

	stdlog.Println("Requested Metrics!")

	*backend.channel <- true

	for {
		select {
		case point := <-*backend.promMetrics:
			tags := point.GetTags(backend.NoArray, ",")
			labelNames := make([]string, len(tags))
			labelValues := make([]string, len(tags))
			i := 0
			for key, value := range tags {
				labelNames[i] = key
				labelValues[i] = value
				i++
			}
			key := point.Group + "_" + point.Counter + "_" + point.Rollup
			desc := prometheus.NewDesc(key, "vSphere collected metric", labelNames, nil)
			metric, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(point.Value), labelValues...)
			if err != nil {
				errlog.Println("E! Error creating prometheus metric")
			}
			ch <- metric
		case <-*backend.doneChannel:
			return
		}
	}
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

package genesis

import (
	"fmt"
	"sync"

	"golang.org/x/net/context"

	"github.com/op/go-logging"
	"github.com/openblockchain/obc-peer/openchain"
	"github.com/openblockchain/obc-peer/openchain/chaincode"
	"github.com/openblockchain/obc-peer/openchain/container"
	"github.com/openblockchain/obc-peer/openchain/crypto"
	"github.com/openblockchain/obc-peer/openchain/ledger"
	"github.com/openblockchain/obc-peer/protos"
	"github.com/spf13/viper"
)

var genesisLogger = logging.MustGetLogger("genesis")

var makeGenesisError error
var once sync.Once

// MakeGenesis creates the genesis block based on configuration in openchain.yaml
// and adds it to the blockchain.
func MakeGenesis(secCxt crypto.Peer) error {
	once.Do(func() {
		ledger, err := ledger.GetLedger()
		if err != nil {
			makeGenesisError = err
			return
		}

		if ledger.GetBlockchainSize() > 0 {
			// genesis block already exists
			return
		}

		genesisLogger.Info("Creating genesis block.")

		ledger.BeginTxBatch(0)
		var genesisTransactions []*protos.Transaction

		genesis := viper.GetStringMap("ledger.blockchain.genesisBlock")

		if genesis == nil {
			genesisLogger.Info("No genesis block chaincodes defined.")
			ledger.CommitTxBatch(0, genesisTransactions, nil)
			return
		}

		chaincodes, chaincodesOK := genesis["chaincode"].([]interface{})
		if !chaincodesOK {
			genesisLogger.Info("No genesis block chaincodes defined.")
			ledger.CommitTxBatch(0, genesisTransactions, nil)
			return
		}

		genesisLogger.Debug("Genesis chaincodes are %s", chaincodes)

		ledger.BeginTxBatch(0)
		for i := 0; i < len(chaincodes); i++ {
			genesisLogger.Debug("Chaincode %d is %s", i, chaincodes[i])

			chaincodeMap, chaincodeMapOK := chaincodes[i].(map[interface{}]interface{})
			if !chaincodeMapOK {
				genesisLogger.Error("Invalid chaincode defined in genesis configuration:", chaincodes[i])
				makeGenesisError = fmt.Errorf("Invalid chaincode defined in genesis configuration: %s", chaincodes[i])
				return
			}

			chaincodeIDMap, chaincodIDOK := chaincodeMap["id"].(map[interface{}]interface{})
			if !chaincodIDOK {
				genesisLogger.Error("Invalid chaincode ID defined in genesis configuration:", chaincodeMap["id"])
				makeGenesisError = fmt.Errorf("Invalid chaincode ID defined in genesis configuration: %s", chaincodeMap["id"])
				return
			}

			url, urlOK := chaincodeIDMap["url"].(string)
			if !urlOK {
				genesisLogger.Error("Invalid chaincode URL defined in genesis configuration:", chaincodeIDMap["url"])
				makeGenesisError = fmt.Errorf("Invalid chaincode URL defined in genesis configuration: %s", chaincodeIDMap["url"])
				return
			}

			version, versionOK := chaincodeIDMap["version"].(string)
			if !versionOK {
				genesisLogger.Error("Invalid chaincode version defined in genesis configuration:", chaincodeIDMap["version"])
				makeGenesisError = fmt.Errorf("Invalid chaincode version defined in genesis configuration: %s", chaincodeIDMap["version"])
				return
			}

			chaincodeType, chaincodeTypeOK := chaincodeMap["type"].(string)
			if !chaincodeTypeOK {
				genesisLogger.Error("Invalid chaincode type defined in genesis configuration:", chaincodeMap["type"])
				makeGenesisError = fmt.Errorf("Invalid chaincode type defined in genesis configuration: %s", chaincodeMap["type"])
				return
			}

			chaincodeID := &protos.ChaincodeID{Url: url, Version: version}

			genesisLogger.Debug("Genesis chaincodeID %s", chaincodeID)
			genesisLogger.Debug("Genesis chaincode type %s", chaincodeType)

			constructorMap, constructorMapOK := chaincodeMap["constructor"].(map[interface{}]interface{})
			if !constructorMapOK {
				genesisLogger.Error("Invalid chaincode constructor defined in genesis configuration:", chaincodeMap["constructor"])
				makeGenesisError = fmt.Errorf("Invalid chaincode constructor defined in genesis configuration: %s", chaincodeMap["constructor"])
				return
			}

			var spec protos.ChaincodeSpec
			if constructorMap == nil {
				genesisLogger.Debug("Genesis chaincode has no constructor.")
				spec = protos.ChaincodeSpec{Type: protos.ChaincodeSpec_Type(protos.ChaincodeSpec_Type_value[chaincodeType]), ChaincodeID: chaincodeID}
			} else {

				ctorFunc, ctorFuncOK := constructorMap["func"].(string)
				if !ctorFuncOK {
					genesisLogger.Error("Invalid chaincode constructor function defined in genesis configuration:", constructorMap["func"])
					makeGenesisError = fmt.Errorf("Invalid chaincode constructor function args defined in genesis configuration: %s", constructorMap["func"])
					return
				}

				ctorArgs, ctorArgsOK := constructorMap["args"].([]interface{})
				if !ctorArgsOK {
					genesisLogger.Error("Invalid chaincode constructor args defined in genesis configuration:", constructorMap["args"])
					makeGenesisError = fmt.Errorf("Invalid chaincode constructor args defined in genesis configuration: %s", constructorMap["args"])
					return
				}

				genesisLogger.Debug("Genesis chaincode constructor func %s", ctorFunc)
				genesisLogger.Debug("Genesis chaincode constructor args %s", ctorArgs)
				var ctorArgsStringArray []string
				for j := 0; j < len(ctorArgs); j++ {
					ctorArgsStringArray = append(ctorArgsStringArray, ctorArgs[j].(string))
				}

				spec = protos.ChaincodeSpec{Type: protos.ChaincodeSpec_Type(protos.ChaincodeSpec_Type_value[chaincodeType]), ChaincodeID: chaincodeID, CtorMsg: &protos.ChaincodeInput{Function: ctorFunc, Args: ctorArgsStringArray}}
			}

			transaction, _, deployErr := DeployLocal(context.Background(), &spec, secCxt)
			if deployErr != nil {
				genesisLogger.Error("Error deploying chaincode for genesis block.", deployErr)
				makeGenesisError = deployErr
				return
			}

			genesisTransactions = append(genesisTransactions, transaction)

		}

		genesisLogger.Info("Adding %d system chaincodes to the genesis block.", len(genesisTransactions))
		ledger.CommitTxBatch(0, genesisTransactions, nil)

	})
	return makeGenesisError
}

//BuildLocal builds a given chaincode code
func BuildLocal(context context.Context, spec *protos.ChaincodeSpec) (*protos.ChaincodeDeploymentSpec, error) {
	genesisLogger.Debug("Received build request for chaincode spec: %v", spec)
	mode := viper.GetString("chaincode.chaincoderunmode")
	var codePackageBytes []byte
	if mode != chaincode.DevModeUserRunsChaincode {
		if err := openchain.CheckSpec(spec); err != nil {
			genesisLogger.Debug("check spec failed: %s", err)
			return nil, err
		}
		// Get new VM and as for building of container image
		vm, err := container.NewVM()
		if err != nil {
			genesisLogger.Error(fmt.Sprintf("Error getting VM: %s", err))
			return nil, err
		}
		// Build the spec
		codePackageBytes, err = vm.BuildChaincodeContainer(spec)
		if err != nil {
			genesisLogger.Error(fmt.Sprintf("Error getting VM: %s", err))
			return nil, err
		}
	}
	chaincodeDeploymentSpec := &protos.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes}
	return chaincodeDeploymentSpec, nil
}

// DeployLocal deploys the supplied chaincode image to the local peer
func DeployLocal(ctx context.Context, spec *protos.ChaincodeSpec, secCxt crypto.Peer) (*protos.Transaction, []byte, error) {
	// First build and get the deployment spec
	chaincodeDeploymentSpec, err := BuildLocal(ctx, spec)

	if err != nil {
		genesisLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
		return nil, nil, err
	}

	// Now create the Transactions message and send to Peer.
	// The UUID must not be random so it will match on all peers.
	uuid := "genesis_" + spec.GetChaincodeID().Url + "_" + spec.GetChaincodeID().Version
	transaction, err := protos.NewChaincodeDeployTransaction(chaincodeDeploymentSpec, uuid)
	if err != nil {
		return nil, nil, fmt.Errorf("Error deploying chaincode: %s ", err)
	}
	//chaincode.NewChaincodeSupport(chaincode.DefaultChain, peer.GetPeerEndpoint, false, 120000)
	result, err := chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction, secCxt)
	return transaction, result, err
}
<commit_msg>Update validity period init deploy added to genesis time<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

package genesis

import (
	"fmt"
	"sync"

	"golang.org/x/net/context"

	"github.com/op/go-logging"
	"github.com/openblockchain/obc-peer/openchain"
	"github.com/openblockchain/obc-peer/openchain/chaincode"
	"github.com/openblockchain/obc-peer/openchain/container"
	"github.com/openblockchain/obc-peer/openchain/crypto"
	"github.com/openblockchain/obc-peer/openchain/ledger"
	"github.com/openblockchain/obc-peer/protos"
	"github.com/spf13/viper"
)

var genesisLogger = logging.MustGetLogger("genesis")

var makeGenesisError error
var once sync.Once

// MakeGenesis creates the genesis block based on configuration in openchain.yaml
// and adds it to the blockchain.
func MakeGenesis(secCxt crypto.Peer) error {
	once.Do(func() {
		ledger, err := ledger.GetLedger()
		if err != nil {
			makeGenesisError = err
			return
		}

		if ledger.GetBlockchainSize() > 0 {
			// genesis block already exists
			return
		}

		genesisLogger.Info("Creating genesis block.")

		ledger.BeginTxBatch(0)
		var genesisTransactions []*protos.Transaction

		vpChaincodePath := "github.com/openblockchain/obc-peer/openchain/system_chaincode/validity_period_update"
		vpChaincodeVersion := "0.0.1"
		vpFunction := "init"
		vpToken := "tca" //TODO It should be configurable, not hardcoded
		var vpCtorArgsStringArray []string

		validityPeriodSpec := &protos.ChaincodeSpec{Type: protos.ChaincodeSpec_GOLANG,
			ChaincodeID: &protos.ChaincodeID{Url: vpChaincodePath,
				Version: vpChaincodeVersion,
			},
			CtorMsg: &protos.ChaincodeInput{Function: vpFunction,
				Args: vpCtorArgsStringArray,
			},
		}

		validityPeriodSpec.SecureContext = string(vpToken)

		vpTransaction, _, deployErr := DeployLocal(context.Background(), validityPeriodSpec, secCxt)

		if deployErr != nil {
			genesisLogger.Error("Error deploying validity period chaincode for genesis block.", deployErr)
			makeGenesisError = deployErr
			genesisLogger.Info("RAULLLLLLLLLLL ERRRRRRRRRRRRRRRRROOOOOOOOOOOOOOOOOOOR NO DEPLOYOOOO")
			return
		}

		genesisLogger.Info("RAULLLLLLLL SIIIIIIIIIIIIIIIIIIIIIIIIII DEPLOYOOOOooo")

		genesisTransactions = append(genesisTransactions, vpTransaction)

		genesis := viper.GetStringMap("ledger.blockchain.genesisBlock")

		if genesis == nil {
			genesisLogger.Info("No genesis block chaincodes defined except for the validity period system chaincode.")
		} else {
			chaincodes, chaincodesOK := genesis["chaincode"].([]interface{})
			if !chaincodesOK {
				genesisLogger.Info("No genesis block chaincodes defined. Validity period update system chaincode was deployed")
				ledger.CommitTxBatch(0, genesisTransactions, nil)
				return
			}

			genesisLogger.Debug("Genesis chaincodes are %s", chaincodes)

			//ledger.BeginTxBatch(0)
			for i := 0; i < len(chaincodes); i++ {
				genesisLogger.Debug("Chaincode %d is %s", i, chaincodes[i])

				chaincodeMap, chaincodeMapOK := chaincodes[i].(map[interface{}]interface{})
				if !chaincodeMapOK {
					genesisLogger.Error("Invalid chaincode defined in genesis configuration:", chaincodes[i])
					makeGenesisError = fmt.Errorf("Invalid chaincode defined in genesis configuration: %s", chaincodes[i])
					return
				}

				chaincodeIDMap, chaincodIDOK := chaincodeMap["id"].(map[interface{}]interface{})
				if !chaincodIDOK {
					genesisLogger.Error("Invalid chaincode ID defined in genesis configuration:", chaincodeMap["id"])
					makeGenesisError = fmt.Errorf("Invalid chaincode ID defined in genesis configuration: %s", chaincodeMap["id"])
					return
				}

				url, urlOK := chaincodeIDMap["url"].(string)
				if !urlOK {
					genesisLogger.Error("Invalid chaincode URL defined in genesis configuration:", chaincodeIDMap["url"])
					makeGenesisError = fmt.Errorf("Invalid chaincode URL defined in genesis configuration: %s", chaincodeIDMap["url"])
					return
				}

				version, versionOK := chaincodeIDMap["version"].(string)
				if !versionOK {
					genesisLogger.Error("Invalid chaincode version defined in genesis configuration:", chaincodeIDMap["version"])
					makeGenesisError = fmt.Errorf("Invalid chaincode version defined in genesis configuration: %s", chaincodeIDMap["version"])
					return
				}

				chaincodeType, chaincodeTypeOK := chaincodeMap["type"].(string)
				if !chaincodeTypeOK {
					genesisLogger.Error("Invalid chaincode type defined in genesis configuration:", chaincodeMap["type"])
					makeGenesisError = fmt.Errorf("Invalid chaincode type defined in genesis configuration: %s", chaincodeMap["type"])
					return
				}

				chaincodeID := &protos.ChaincodeID{Url: url, Version: version}

				genesisLogger.Debug("Genesis chaincodeID %s", chaincodeID)
				genesisLogger.Debug("Genesis chaincode type %s", chaincodeType)

				constructorMap, constructorMapOK := chaincodeMap["constructor"].(map[interface{}]interface{})
				if !constructorMapOK {
					genesisLogger.Error("Invalid chaincode constructor defined in genesis configuration:", chaincodeMap["constructor"])
					makeGenesisError = fmt.Errorf("Invalid chaincode constructor defined in genesis configuration: %s", chaincodeMap["constructor"])
					return
				}

				var spec protos.ChaincodeSpec
				if constructorMap == nil {
					genesisLogger.Debug("Genesis chaincode has no constructor.")
					spec = protos.ChaincodeSpec{Type: protos.ChaincodeSpec_Type(protos.ChaincodeSpec_Type_value[chaincodeType]), ChaincodeID: chaincodeID}
				} else {

					ctorFunc, ctorFuncOK := constructorMap["func"].(string)
					if !ctorFuncOK {
						genesisLogger.Error("Invalid chaincode constructor function defined in genesis configuration:", constructorMap["func"])
						makeGenesisError = fmt.Errorf("Invalid chaincode constructor function args defined in genesis configuration: %s", constructorMap["func"])
						return
					}

					ctorArgs, ctorArgsOK := constructorMap["args"].([]interface{})
					if !ctorArgsOK {
						genesisLogger.Error("Invalid chaincode constructor args defined in genesis configuration:", constructorMap["args"])
						makeGenesisError = fmt.Errorf("Invalid chaincode constructor args defined in genesis configuration: %s", constructorMap["args"])
						return
					}

					genesisLogger.Debug("Genesis chaincode constructor func %s", ctorFunc)
					genesisLogger.Debug("Genesis chaincode constructor args %s", ctorArgs)
					var ctorArgsStringArray []string
					for j := 0; j < len(ctorArgs); j++ {
						ctorArgsStringArray = append(ctorArgsStringArray, ctorArgs[j].(string))
					}

					spec = protos.ChaincodeSpec{Type: protos.ChaincodeSpec_Type(protos.ChaincodeSpec_Type_value[chaincodeType]), ChaincodeID: chaincodeID, CtorMsg: &protos.ChaincodeInput{Function: ctorFunc, Args: ctorArgsStringArray}}
				}

				transaction, _, deployErr := DeployLocal(context.Background(), &spec, secCxt)
				if deployErr != nil {
					genesisLogger.Error("Error deploying chaincode for genesis block.", deployErr)
					makeGenesisError = deployErr
					return
				}

				genesisTransactions = append(genesisTransactions, transaction)

			} //for
		} //if

		genesisLogger.Info("Adding %d system chaincodes to the genesis block.", len(genesisTransactions))
		ledger.CommitTxBatch(0, genesisTransactions, nil)

	})
	return makeGenesisError
}

//BuildLocal builds a given chaincode code
func BuildLocal(context context.Context, spec *protos.ChaincodeSpec) (*protos.ChaincodeDeploymentSpec, error) {
	genesisLogger.Debug("Received build request for chaincode spec: %v", spec)
	mode := viper.GetString("chaincode.chaincoderunmode")
	var codePackageBytes []byte
	if mode != chaincode.DevModeUserRunsChaincode {
		if err := openchain.CheckSpec(spec); err != nil {
			genesisLogger.Debug("check spec failed: %s", err)
			return nil, err
		}
		// Get new VM and as for building of container image
		vm, err := container.NewVM()
		if err != nil {
			genesisLogger.Error(fmt.Sprintf("Error getting VM: %s", err))
			return nil, err
		}
		// Build the spec
		codePackageBytes, err = vm.BuildChaincodeContainer(spec)
		if err != nil {
			genesisLogger.Error(fmt.Sprintf("Error getting VM: %s", err))
			return nil, err
		}
	}
	chaincodeDeploymentSpec := &protos.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes}
	return chaincodeDeploymentSpec, nil
}

// DeployLocal deploys the supplied chaincode image to the local peer
func DeployLocal(ctx context.Context, spec *protos.ChaincodeSpec, secCxt crypto.Peer) (*protos.Transaction, []byte, error) {
	// First build and get the deployment spec
	chaincodeDeploymentSpec, err := BuildLocal(ctx, spec)

	if err != nil {
		genesisLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
		return nil, nil, err
	}

	// Now create the Transactions message and send to Peer.
	// The UUID must not be random so it will match on all peers.
	uuid := "genesis_" + spec.GetChaincodeID().Url + "_" + spec.GetChaincodeID().Version
	transaction, err := protos.NewChaincodeDeployTransaction(chaincodeDeploymentSpec, uuid)
	if err != nil {
		return nil, nil, fmt.Errorf("Error deploying chaincode: %s ", err)
	}
	//chaincode.NewChaincodeSupport(chaincode.DefaultChain, peer.GetPeerEndpoint, false, 120000)
	result, err := chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction, secCxt)
	return transaction, result, err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"math/rand"
	"net/mail"
	"net/smtp"
	"net/textproto"
	"os"
	"os/user"
	"reflect"
	"regexp"
	"strings"
	"time"
	"crypto/tls"
	"github.com/blackjack/syslog"
)

var config = &Configuration{
	Verbose:     false,
	ConfigFile:  "/etc/go-ssmtp.ini",
	Port:        25,
	Server:      "127.0.0.1",
	Postmaster:  "postmaster",
	ScanMessage: false,
}

type Configuration struct {
	Verbose                      bool
	ConfigFile                   string
	Hostname                     string
	Server                       string
	Port                         int
	Postmaster                   string
	ScanMessage                  bool
	Authentication_User          string
	Authentication_Password      string
	Authentication_Identity      string
	Authentication_Mechanism     string
	Authentication_ForceStartTLS bool
	Message_To                   []string
	Message_From                 string
	Message_FromName             string
	Message_FromCronDaemon       bool
}

func generateMessageId() string {
	const CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	bytes := make([]byte, 16)

	for i, r := 0, rand.New(rand.NewSource(time.Now().UnixNano())); i < len(bytes); i++ {
		bytes[i] = CHARS[r.Intn(len(CHARS))]
	}

	return string(bytes)
}

func (c *Configuration) ParseFile(file string) error {
	var matchSection = regexp.MustCompile(`^\[([^]]+)\]$`)
	var matchPair = regexp.MustCompile(`^([^#;=]+)=(.*)$`)

	f, err := os.Open(file)

	if err != nil {
		return err
	}

	defer f.Close()

	s := bufio.NewScanner(f)
	s.Split(bufio.ScanLines)
	var n, section = 1, ""

	for s.Scan() {
		l := s.Text()

		if 0 == len(l) || ';' == l[0] {
			continue
		} else if parts := matchSection.FindStringSubmatch(l); parts != nil {
			section = parts[1]
		} else if parts := matchPair.FindStringSubmatch(l); parts != nil {
			k, v := parts[1], parts[2]

			if section != "" {
				k = section + "_" + k
			}

			if !c.Get(k).IsValid() {
				fmt.Fprintf(os.Stderr, "Warning: unknown configuration variable %s, line %d\n", k, n)
			} else if "string" == config.Get(k).Type().String() {
				c.Get(k).SetString(v)
			} else if "bool" == config.Get(k).Type().String() {
				c.Get(k).SetBool("1" == v)
			}
		} else {
			return fmt.Errorf("Failed to parse config, line %d: %s", n, l)
		}

		n++
	}

	return nil
}

func (c *Configuration) Get(k string) reflect.Value {
	r := reflect.ValueOf(c)
	return reflect.Indirect(r).FieldByName(k)
}

func compose() (*mail.Message, error) {
	// Make sure we can re-use Stdin even after being consumed by mail.ReadMessage
	b := bytes.Buffer{}
	b.ReadFrom(os.Stdin)
	msg := b.String()

	m, err := mail.ReadMessage(bytes.NewBufferString(msg))
	if err != nil {
		if config.ScanMessage {
			return nil, fmt.Errorf("ScanMessage: cannot parse message: %s", err)
		}

		// Assume there are no headers in the message
		m = &mail.Message{
			Header: mail.Header(textproto.MIMEHeader{}),
			Body:   bufio.NewReader(bytes.NewBufferString(msg)),
		}
	}

	// Make sure all required fields are set
	if 0 == len(m.Header["From"]) {
		m.Header["From"] = []string{(&mail.Address{config.Message_FromName, config.Message_From}).String()}
	} else if from, err := mail.ParseAddress(m.Header["From"][0]); config.ScanMessage && err == nil {
		// Parse and put in config; to be used by c.Mail
		config.Message_From = from.Address;
	}

	if 0 == len(m.Header["To"]) {
		m.Header["To"] = config.Message_To
	}

	if 0 == len(m.Header["Date"]) {
		m.Header["Date"] = []string{time.Now().Format("Mon, 2 Jan 2006 15:04:05 -0700")}
	}

	if 0 == len(m.Header["Message-Id"]) {
		m.Header["Message-Id"] = []string{"<GOSSMTP." + generateMessageId() + "@" + config.Hostname + ">"}
	}

	return m, nil
}

func connect() (*smtp.Client, error) {
	c, err := smtp.Dial(fmt.Sprintf("%s:%d", config.Server, config.Port))

	if err != nil {
		return nil, fmt.Errorf("while connecting to %s on port %d: %s", config.Server, config.Port, err)
	}

	if err := c.Hello(config.Hostname); err != nil {
		return nil, fmt.Errorf("while sending Hello `%s`: %s", config.Hostname, err)
	}

	if ok, _ := c.Extension("STARTTLS"); ok {
			if err = c.StartTLS(&tls.Config{ServerName: config.Server}); err != nil {
			return nil, fmt.Errorf("while enabling startTLS: %s", err)
		}
	} else if config.Authentication_ForceStartTLS {
		return nil, fmt.Errorf("server does not support StartTLS")
	}

	switch config.Authentication_Mechanism {
	case "CRAM-MD5":
		auth := smtp.CRAMMD5Auth(
			config.Authentication_User,
			config.Authentication_Password,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				return nil, fmt.Errorf("Info: using authentication: CRAM-MD5")
			}
		}

	case "PLAIN":
		auth := smtp.PlainAuth(
			config.Authentication_Identity,
			config.Authentication_User,
			config.Authentication_Password,
			config.Server,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				fmt.Println("Info: using authentication: PLAIN")
			}
		}

	default:
		if config.Verbose {
			fmt.Println("Info: not using authentication")
		}
	}

	return c, nil
}

func addRecipientsFromHeader(m *mail.Message, i string) {
	if 0 == len(m.Header[i]) {
		return
	}

	if l, err := m.Header.AddressList(i); err != nil {
		fmt.Fprintf(os.Stderr, "ScanMessage: Could not parse recipients in %s `%s`; %s", i, l, err)
	} else {
		for _, v := range l {
			config.Message_To = append(config.Message_To, v.Address)
		}
	}
}

func send(c *smtp.Client, m *mail.Message) error {
	if err := c.Mail(config.Message_From); err != nil {
		return fmt.Errorf("while setting From `%s`: %s", config.Message_From, err)
	}

	if config.ScanMessage {
		addRecipientsFromHeader(m, "To")
		addRecipientsFromHeader(m, "Cc")
		addRecipientsFromHeader(m, "Bcc")

		if 0 == len(config.Message_To) {
			fmt.Fprintln(os.Stderr, "ScanMessage: No recipients found in message-body")
		}
	}

	for _, to := range config.Message_To {
		if err := c.Rcpt(to); err != nil {
			return fmt.Errorf("while setting Recipient `%s`: %s", to, err)
		}
	}

	w, err := c.Data()
	if err != nil {
		return fmt.Errorf("while setting Data: %s", err)
	}

	var s = ""
	for k, h := range m.Header {
		for _, v := range h {
			s += k + ": " + v + "\r\n"
		}
	}

	b := bytes.Buffer{}
	b.ReadFrom(m.Body)

	if _, err := w.Write([]byte(s + "\r\n" + b.String())); err != nil {
		return fmt.Errorf("while sending message: %s", err)
	}

	if err = w.Close(); err != nil {
		return fmt.Errorf("while closing message: %s", err)
	}

	if err = c.Quit(); err != nil {
		return fmt.Errorf("while closing connection: %s", err)
	}

	return nil
}

func init() {
	if h, err := os.Hostname(); err == nil {
		config.Hostname = h
	} else {
		config.Hostname = "localhost"
	}

	if u, err := user.Current(); err == nil {
		config.Message_From = u.Username + "@" + config.Hostname

		if u.Name != "" {
			config.Message_FromName = u.Name
		} else {
			config.Message_FromName = u.Username
		}
	}

	if -1 == strings.Index(config.Postmaster, "@") {
		config.Postmaster += "@" + config.Hostname
	}

	syslog.Openlog("go-ssmtp", syslog.LOG_PID, syslog.LOG_USER)

	var ignore bool
	flag.BoolVar(&ignore, "i", false, "Ignore")
	flag.BoolVar(&ignore, "odi", false, "Ignore")
	flag.BoolVar(&config.Message_FromCronDaemon, "FCronDaemon", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Message_FromCronDaemon, "FAnacron", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Verbose, "v", config.Verbose, "Enable verbose mode")
	flag.StringVar(&config.ConfigFile, "C", config.ConfigFile, "Use alternate configuration file")
	flag.StringVar(&config.Message_From, "f", config.Message_From, "Manually specify the sender-address of the email")
	flag.StringVar(&config.Message_FromName, "F", config.Message_FromName, "Manually specify the sender-name of the email")
	flag.BoolVar(&config.ScanMessage, "t", config.ScanMessage, "Scan message for recipients")
}

func main() {
	// Don't throw an error when encountering an unknown flag (for sendmail compat)
	flag.CommandLine.Init(os.Args[0], flag.ContinueOnError)

	flag.Parse()

	if config.Message_FromCronDaemon {
		config.Message_FromName = "CronDaemon"
	}

	// Map all local users to Postmaster address
	config.Message_To = flag.Args()
	for i, to := range config.Message_To {
		if -1 == strings.Index(to, "@") {
			config.Message_To[i] = (&mail.Address{to, config.Postmaster}).String()
		}
	}

	if err := config.ParseFile(config.ConfigFile); err != nil {
		fmt.Fprintf(os.Stderr, "Error while parsing configuration: %s\n", err)
		os.Exit(2)
	}

	if config.Verbose {
		fmt.Printf("%#v\n", *config)
	}

	if len(config.Message_To) == 0 && !config.ScanMessage {
		fmt.Fprintln(os.Stderr, "Error: no recipients supplied")
		os.Exit(1)
	}

	m, err := compose()
	if err != nil {
		syslog.Errf("ComposeError: %s", err)
		fmt.Fprintf(os.Stderr, "ComposeError: %s\n", err)
		os.Exit(2)
	}

	c, err := connect()
	if err != nil {
		syslog.Errf("ConnectError: %s", err)
		fmt.Fprintf(os.Stderr, "ConnectError: %s\n", err)
		os.Exit(3)
	}

	if err := send(c, m); err != nil {
		syslog.Errf("SendError: %s", err)
		fmt.Fprintf(os.Stderr, "SendError: %s\n", err)
		os.Exit(4)
	}

	var subject string = "(unknown)"
	if len(m.Header["Subject"]) > 0 {
		subject = m.Header["Subject"][0]
	}

	syslog.Syslogf(syslog.LOG_INFO, "[%s] Sent mail; subject \"%s\"; from %s; to %#v", m.Header["Message-Id"][0], subject, config.Message_From, config.Message_To);

	if config.Verbose {
		fmt.Println("Info: send successful")
	}
}
<commit_msg>No longer need separate method, inline it<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"math/rand"
	"net/mail"
	"net/smtp"
	"net/textproto"
	"os"
	"os/user"
	"reflect"
	"regexp"
	"strings"
	"time"
	"crypto/tls"
	"github.com/blackjack/syslog"
)

var config = &Configuration{
	Verbose:     false,
	ConfigFile:  "/etc/go-ssmtp.ini",
	Port:        25,
	Server:      "127.0.0.1",
	Postmaster:  "postmaster",
	ScanMessage: false,
}

type Configuration struct {
	Verbose                      bool
	ConfigFile                   string
	Hostname                     string
	Server                       string
	Port                         int
	Postmaster                   string
	ScanMessage                  bool
	Authentication_User          string
	Authentication_Password      string
	Authentication_Identity      string
	Authentication_Mechanism     string
	Authentication_ForceStartTLS bool
	Message_To                   []string
	Message_From                 string
	Message_FromName             string
	Message_FromCronDaemon       bool
}

func generateMessageId() string {
	const CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	bytes := make([]byte, 16)

	for i, r := 0, rand.New(rand.NewSource(time.Now().UnixNano())); i < len(bytes); i++ {
		bytes[i] = CHARS[r.Intn(len(CHARS))]
	}

	return string(bytes)
}

func (c *Configuration) ParseFile(file string) error {
	var matchSection = regexp.MustCompile(`^\[([^]]+)\]$`)
	var matchPair = regexp.MustCompile(`^([^#;=]+)=(.*)$`)

	f, err := os.Open(file)

	if err != nil {
		return err
	}

	defer f.Close()

	s := bufio.NewScanner(f)
	s.Split(bufio.ScanLines)
	var n, section = 1, ""

	for s.Scan() {
		l := s.Text()

		if 0 == len(l) || ';' == l[0] {
			continue
		} else if parts := matchSection.FindStringSubmatch(l); parts != nil {
			section = parts[1]
		} else if parts := matchPair.FindStringSubmatch(l); parts != nil {
			k, v := parts[1], parts[2]

			if section != "" {
				k = section + "_" + k
			}

			if !c.Get(k).IsValid() {
				fmt.Fprintf(os.Stderr, "Warning: unknown configuration variable %s, line %d\n", k, n)
			} else if "string" == config.Get(k).Type().String() {
				c.Get(k).SetString(v)
			} else if "bool" == config.Get(k).Type().String() {
				c.Get(k).SetBool("1" == v)
			}
		} else {
			return fmt.Errorf("Failed to parse config, line %d: %s", n, l)
		}

		n++
	}

	return nil
}

func (c *Configuration) Get(k string) reflect.Value {
	r := reflect.ValueOf(c)
	return reflect.Indirect(r).FieldByName(k)
}

func compose() (*mail.Message, error) {
	// Make sure we can re-use Stdin even after being consumed by mail.ReadMessage
	b := bytes.Buffer{}
	b.ReadFrom(os.Stdin)
	msg := b.String()

	m, err := mail.ReadMessage(bytes.NewBufferString(msg))
	if err != nil {
		if config.ScanMessage {
			return nil, fmt.Errorf("ScanMessage: cannot parse message: %s", err)
		}

		// Assume there are no headers in the message
		m = &mail.Message{
			Header: mail.Header(textproto.MIMEHeader{}),
			Body:   bufio.NewReader(bytes.NewBufferString(msg)),
		}
	}

	// Make sure all required fields are set
	if 0 == len(m.Header["From"]) {
		m.Header["From"] = []string{(&mail.Address{config.Message_FromName, config.Message_From}).String()}
	} else if from, err := mail.ParseAddress(m.Header["From"][0]); config.ScanMessage && err == nil {
		// Parse and put in config; to be used by c.Mail
		config.Message_From = from.Address;
	}

	if 0 == len(m.Header["To"]) {
		m.Header["To"] = config.Message_To
	}

	if 0 == len(m.Header["Date"]) {
		m.Header["Date"] = []string{time.Now().Format("Mon, 2 Jan 2006 15:04:05 -0700")}
	}

	if 0 == len(m.Header["Message-Id"]) {
		m.Header["Message-Id"] = []string{"<GOSSMTP." + generateMessageId() + "@" + config.Hostname + ">"}
	}

	return m, nil
}

func connect() (*smtp.Client, error) {
	c, err := smtp.Dial(fmt.Sprintf("%s:%d", config.Server, config.Port))

	if err != nil {
		return nil, fmt.Errorf("while connecting to %s on port %d: %s", config.Server, config.Port, err)
	}

	if err := c.Hello(config.Hostname); err != nil {
		return nil, fmt.Errorf("while sending Hello `%s`: %s", config.Hostname, err)
	}

	if ok, _ := c.Extension("STARTTLS"); ok {
			if err = c.StartTLS(&tls.Config{ServerName: config.Server}); err != nil {
			return nil, fmt.Errorf("while enabling startTLS: %s", err)
		}
	} else if config.Authentication_ForceStartTLS {
		return nil, fmt.Errorf("server does not support StartTLS")
	}

	switch config.Authentication_Mechanism {
	case "CRAM-MD5":
		auth := smtp.CRAMMD5Auth(
			config.Authentication_User,
			config.Authentication_Password,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				return nil, fmt.Errorf("Info: using authentication: CRAM-MD5")
			}
		}

	case "PLAIN":
		auth := smtp.PlainAuth(
			config.Authentication_Identity,
			config.Authentication_User,
			config.Authentication_Password,
			config.Server,
		)

		if ok, _ := c.Extension("AUTH"); ok {
			if err = c.Auth(auth); err != nil {
				return nil, fmt.Errorf("while authenticating: %s", err)
			} else if config.Verbose {
				fmt.Println("Info: using authentication: PLAIN")
			}
		}

	default:
		if config.Verbose {
			fmt.Println("Info: not using authentication")
		}
	}

	return c, nil
}

func send(c *smtp.Client, m *mail.Message) error {
	if err := c.Mail(config.Message_From); err != nil {
		return fmt.Errorf("while setting From `%s`: %s", config.Message_From, err)
	}

	if config.ScanMessage {
		for _, i := range []string{"To", "Cc", "Bcc"} {
			if 0 == len(m.Header[i]) {
				continue
			}

			if l, err := m.Header.AddressList(i); err != nil {
				fmt.Fprintf(os.Stderr, "ScanMessage: Could not parse recipients in %s `%s`; %s", i, l, err)
			} else {
				for _, v := range l {
					config.Message_To = append(config.Message_To, v.Address)
				}
			}
		}

		if 0 == len(config.Message_To) {
			fmt.Fprintln(os.Stderr, "ScanMessage: No recipients found in message-body")
		}
	}

	for _, to := range config.Message_To {
		if err := c.Rcpt(to); err != nil {
			return fmt.Errorf("while setting Recipient `%s`: %s", to, err)
		}
	}

	w, err := c.Data()
	if err != nil {
		return fmt.Errorf("while setting Data: %s", err)
	}

	var s = ""
	for k, h := range m.Header {
		for _, v := range h {
			s += k + ": " + v + "\r\n"
		}
	}

	b := bytes.Buffer{}
	b.ReadFrom(m.Body)

	if _, err := w.Write([]byte(s + "\r\n" + b.String())); err != nil {
		return fmt.Errorf("while sending message: %s", err)
	}

	if err = w.Close(); err != nil {
		return fmt.Errorf("while closing message: %s", err)
	}

	if err = c.Quit(); err != nil {
		return fmt.Errorf("while closing connection: %s", err)
	}

	return nil
}

func init() {
	if h, err := os.Hostname(); err == nil {
		config.Hostname = h
	} else {
		config.Hostname = "localhost"
	}

	if u, err := user.Current(); err == nil {
		config.Message_From = u.Username + "@" + config.Hostname

		if u.Name != "" {
			config.Message_FromName = u.Name
		} else {
			config.Message_FromName = u.Username
		}
	}

	if -1 == strings.Index(config.Postmaster, "@") {
		config.Postmaster += "@" + config.Hostname
	}

	syslog.Openlog("go-ssmtp", syslog.LOG_PID, syslog.LOG_USER)

	var ignore bool
	flag.BoolVar(&ignore, "i", false, "Ignore")
	flag.BoolVar(&ignore, "odi", false, "Ignore")
	flag.BoolVar(&config.Message_FromCronDaemon, "FCronDaemon", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Message_FromCronDaemon, "FAnacron", false, "Hack to allow crond to work with flag pkg")
	flag.BoolVar(&config.Verbose, "v", config.Verbose, "Enable verbose mode")
	flag.StringVar(&config.ConfigFile, "C", config.ConfigFile, "Use alternate configuration file")
	flag.StringVar(&config.Message_From, "f", config.Message_From, "Manually specify the sender-address of the email")
	flag.StringVar(&config.Message_FromName, "F", config.Message_FromName, "Manually specify the sender-name of the email")
	flag.BoolVar(&config.ScanMessage, "t", config.ScanMessage, "Scan message for recipients")
}

func main() {
	// Don't throw an error when encountering an unknown flag (for sendmail compat)
	flag.CommandLine.Init(os.Args[0], flag.ContinueOnError)

	flag.Parse()

	if config.Message_FromCronDaemon {
		config.Message_FromName = "CronDaemon"
	}

	// Map all local users to Postmaster address
	config.Message_To = flag.Args()
	for i, to := range config.Message_To {
		if -1 == strings.Index(to, "@") {
			config.Message_To[i] = (&mail.Address{to, config.Postmaster}).String()
		}
	}

	if err := config.ParseFile(config.ConfigFile); err != nil {
		fmt.Fprintf(os.Stderr, "Error while parsing configuration: %s\n", err)
		os.Exit(2)
	}

	if config.Verbose {
		fmt.Printf("%#v\n", *config)
	}

	if len(config.Message_To) == 0 && !config.ScanMessage {
		fmt.Fprintln(os.Stderr, "Error: no recipients supplied")
		os.Exit(1)
	}

	m, err := compose()
	if err != nil {
		syslog.Errf("ComposeError: %s", err)
		fmt.Fprintf(os.Stderr, "ComposeError: %s\n", err)
		os.Exit(2)
	}

	c, err := connect()
	if err != nil {
		syslog.Errf("ConnectError: %s", err)
		fmt.Fprintf(os.Stderr, "ConnectError: %s\n", err)
		os.Exit(3)
	}

	if err := send(c, m); err != nil {
		syslog.Errf("SendError: %s", err)
		fmt.Fprintf(os.Stderr, "SendError: %s\n", err)
		os.Exit(4)
	}

	var subject string = "(unknown)"
	if len(m.Header["Subject"]) > 0 {
		subject = m.Header["Subject"][0]
	}

	syslog.Syslogf(syslog.LOG_INFO, "[%s] Sent mail; subject \"%s\"; from %s; to %#v", m.Header["Message-Id"][0], subject, config.Message_From, config.Message_To);

	if config.Verbose {
		fmt.Println("Info: send successful")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"strings"

	"code.google.com/p/go.net/html"
	"code.google.com/p/go.net/html/atom"
	"github.com/JustinTulloss/hut"
	"github.com/temoto/robotstxt.go"
)

var ogmatcher = regexp.MustCompile("^(og|airbedandbreakfast|twitter):")
var useragent = "Gogetter (https://github.com/JustinTulloss/gogetter) (like GoogleBot)"
var service *hut.Service

type HttpError struct {
	msg        string
	StatusCode int
}

func (e *HttpError) Error() string { return e.msg }

func buildRequest(url string) (*http.Request, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", useragent)
	return req, nil
}

func checkRobotsTxt(fullUrl string) (bool, error) {
	parsed, err := url.Parse(fullUrl)
	if err != nil {
		return false, err
	}
	original := parsed.Path
	parsed.Path = "robots.txt"
	client := http.Client{}
	req, err := buildRequest(parsed.String())
	if err != nil {
		return false, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()
	robots, err := robotstxt.FromResponse(resp)
	if robots == nil {
		// Assume we can crawl if the robots.txt file doesn't work
		return true, nil
	}
	return robots.TestAgent(original, useragent), nil
}

func parseTags(r io.Reader) (map[string]string, *HttpError) {
	node, err := html.Parse(r)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	var findmeta func(*html.Node)
	results := make(map[string]string)
	// Recursively goes through nodes looking for meta nodes that
	// have a property tag that matches the opengraph regex. If it does,
	// Saves the contents to the results map.
	findmeta = func(n *html.Node) {
		if n.Type == html.ElementNode && n.DataAtom == atom.Meta {
			var content, property string
			save := false
			for _, a := range n.Attr {
				if (a.Key == "property" || a.Key == "name") && ogmatcher.FindStringIndex(a.Val) != nil {
					save = true
					property = html.UnescapeString(a.Val)
				}
				if a.Key == "content" {
					content = html.UnescapeString(a.Val)
				}
			}
			if save {
				results[property] = content
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			findmeta(c)
		}
	}
	findmeta(node)
	return results, nil
}

func getTags(url string) (map[string]string, *HttpError) {
	permitted, err := checkRobotsTxt(url)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	if !permitted {
		msg := fmt.Sprintf("Not permitted to fetch %s as a robot", url)
		log.Println(msg)
		return nil, &HttpError{msg, 403}
	}
	client := http.Client{}
	req, _ := buildRequest(url)
	resp, err := client.Do(req)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	log.Printf("Fetched %s\n", url)
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, &HttpError{
			fmt.Sprintf("Could not fetch %s", url),
			resp.StatusCode,
		}
	}
	return parseTags(resp.Body)
}

func handler(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		service.ErrorReply(err, w)
		return
	}
	tags, err := getTags(strings.TrimPrefix(r.Form.Get("url"), "/"))
	if err != nil {
		service.HttpErrorReply(w, err.Error(), err.StatusCode)
		return
	}
	service.Reply(tags, w)
}

func main() {
	service = hut.NewService(nil)
	service.Router.HandleFunc("/", handler)

	protocol, err := service.Env.Get("protocol")
	if err != nil {
		log.Fatal(err)
	}
	if protocol == "http" {
		service.Start()
	} else if len(flag.Args()) != 0 {
		tags, _ := getTags(flag.Arg(0))
		for prop, val := range tags {
			fmt.Printf("%s -- %s\n", prop, val)
		}
	} else {
		panic("Need to use this properly and I need to print usage info!")
	}
}
<commit_msg>Deal with encoded parameters correctly<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"regexp"

	"code.google.com/p/go.net/html"
	"code.google.com/p/go.net/html/atom"
	"github.com/JustinTulloss/hut"
	"github.com/temoto/robotstxt.go"
)

var ogmatcher = regexp.MustCompile("^(og|airbedandbreakfast|twitter):")
var useragent = "Gogetter (https://github.com/JustinTulloss/gogetter) (like GoogleBot)"
var service *hut.Service

type HttpError struct {
	msg        string
	StatusCode int
}

func (e *HttpError) Error() string { return e.msg }

func buildRequest(url string) (*http.Request, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", useragent)
	return req, nil
}

func checkRobotsTxt(fullUrl string) (bool, error) {
	parsed, err := url.Parse(fullUrl)
	if err != nil {
		return false, err
	}
	original := parsed.Path
	parsed.Path = "robots.txt"
	client := http.Client{}
	req, err := buildRequest(parsed.String())
	if err != nil {
		return false, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()
	robots, err := robotstxt.FromResponse(resp)
	if robots == nil {
		// Assume we can crawl if the robots.txt file doesn't work
		return true, nil
	}
	return robots.TestAgent(original, useragent), nil
}

func parseTags(r io.Reader) (map[string]string, *HttpError) {
	node, err := html.Parse(r)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	var findmeta func(*html.Node)
	results := make(map[string]string)
	// Recursively goes through nodes looking for meta nodes that
	// have a property tag that matches the opengraph regex. If it does,
	// Saves the contents to the results map.
	findmeta = func(n *html.Node) {
		if n.Type == html.ElementNode && n.DataAtom == atom.Meta {
			var content, property string
			save := false
			for _, a := range n.Attr {
				if (a.Key == "property" || a.Key == "name") && ogmatcher.FindStringIndex(a.Val) != nil {
					save = true
					property = html.UnescapeString(a.Val)
				}
				if a.Key == "content" {
					content = html.UnescapeString(a.Val)
				}
			}
			if save {
				results[property] = content
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			findmeta(c)
		}
	}
	findmeta(node)
	return results, nil
}

func getTags(url string) (map[string]string, *HttpError) {
	permitted, err := checkRobotsTxt(url)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	if !permitted {
		msg := fmt.Sprintf("Not permitted to fetch %s as a robot", url)
		log.Println(msg)
		return nil, &HttpError{msg, 403}
	}
	client := http.Client{}
	req, _ := buildRequest(url)
	resp, err := client.Do(req)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	log.Printf("Fetched %s\n", url)
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, &HttpError{
			fmt.Sprintf("Could not fetch %s", url),
			resp.StatusCode,
		}
	}
	return parseTags(resp.Body)
}

func handler(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		service.ErrorReply(err, w)
		return
	}
	decodedUrl, err := url.QueryUnescape(r.Form.Get("url"))
	if err != nil {
		service.ErrorReply(err, w)
		return
	}
	tags, httpErr := getTags(decodedUrl)
	if httpErr != nil {
		service.HttpErrorReply(w, httpErr.Error(), httpErr.StatusCode)
		return
	}
	service.Reply(tags, w)
}

func main() {
	service = hut.NewService(nil)
	service.Router.HandleFunc("/", handler)

	protocol, err := service.Env.Get("protocol")
	if err != nil {
		log.Fatal(err)
	}
	if protocol == "http" {
		service.Start()
	} else if len(flag.Args()) != 0 {
		tags, _ := getTags(flag.Arg(0))
		for prop, val := range tags {
			fmt.Printf("%s -- %s\n", prop, val)
		}
	} else {
		panic("Need to use this properly and I need to print usage info!")
	}
}
<|endoftext|>


<commit_before>package main

import "os"
import "io"
import "path"
import "flag"
import "bufio"
import "bytes"
import "runtime"
import "crypto/aes"
import "crypto/rand"
import "crypto/cipher"
import "fmt"

const DESCRIPTION = `
Another pseudo-random number generator (PRNG). This was designed to be a faster
alternative to the built-in /dev/urandom device built into most Linux kernels.
This PRNG is based on the Advanced Encryption Standard (AES) cipher operating
in cipher-block chaining (CBC) mode. This implementation is capable of spawning
multiple rountines that generate pseudo-random data in parallel.

By default, this generator will spawn off a number of routines equal to the
number of logical cores in an attempt to maximize the output. If the output
is not being consumed as fast as data is being generated, routines can block.
As a result, CPU utilization may go down, allowing other processes to run.
`

var NumJobs, NumBlocks int

func RandGen(comm chan io.Reader, quit chan bool) {
	data := make([]byte, aes.BlockSize*NumBlocks)
	for {
		// Generate a random new encryption key
		key := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, key); num != aes.BlockSize {
			panic("Could not seed a random cryptographic key.")
		}

		// Create the encryption cipher
		aesCipher, err := aes.NewCipher(key)
		if err != nil {
			panic("Could not create a new AES cipher.")
		}

		// Generate a random initialization vector for cipher block chaining
		vector := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, vector); num != aes.BlockSize {
			panic("Could not seed a random initialization vector.")
		}

		// Use CBC to generate pseudo-random data
		cbcCipher := cipher.NewCBCEncrypter(aesCipher, vector)
		cbcCipher.CryptBlocks(data, data)
		buf := bytes.NewBuffer(data)

		// Send data to main routine
		select {
		case comm <- buf:
			continue
		case <-quit:
			break
		}
	}
}

func main() {
	comm := make(chan io.Reader)
	quit := make(chan bool)

	// Command-line parser
	fs := flag.NewFlagSet("", flag.ExitOnError)
	fs.Usage = func() {
		cmd := path.Base(os.Args[0])
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", cmd)
		fmt.Fprintln(os.Stderr, DESCRIPTION)
		fs.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n")
		fmt.Fprintf(os.Stderr, "Report '%s' bugs to joetsai@digital-static.net\n", cmd)
	}
	fs.IntVar(&NumJobs, "jobs", runtime.NumCPU(), "Number of Go-routines jobs to spin off.")
	fs.IntVar(&NumBlocks, "blocks", (1 << 16), "Each routine will generate this many pseudo-random blocks before re-seeding.")
	fs.Parse(os.Args[1:])
	if NumJobs <= 0 {
		fmt.Fprintln(os.Stderr, "Number of jobs must be positive.")
	}
	if NumBlocks <= 0 {
		fmt.Fprintln(os.Stderr, "Number of blocks to generate must be positive.")
	}

	// Spin off a great number of workers
	runtime.GOMAXPROCS(NumJobs)
	for i := 0; i < NumJobs; i++ {
		go RandGen(comm, quit)
	}

	// Continually read data from workers
	dstBuf := bufio.NewWriter(os.Stdout)
	for {
		srcBuf := <-comm
		if _, err := io.Copy(dstBuf, srcBuf); err != nil {
			close(quit)
			break
		}
	}
}
<commit_msg>Made minor modification to the comments.<commit_after>package main

import "os"
import "io"
import "fmt"
import "path"
import "flag"
import "bufio"
import "bytes"
import "runtime"
import "crypto/aes"
import "crypto/rand"
import "crypto/cipher"

const DESCRIPTION = `
Another pseudo-random number generator (PRNG). This was designed to be a faster
alternative to the /dev/urandom device built into most Linux kernels. This PRNG
is based on the Advanced Encryption Standard (AES) cipher operating in
cipher-block chaining (CBC) mode. Both the AES key and CBC initialization vector
will be seeded from the operating system's cryptographically secure PRNG.

This implementation is capable of spawning multiple rountines that generate
pseudo-random data in parallel. By default, this generator will spawn off a
number of routines equal to the number of logical cores in an attempt to
maximize the output. If the output is not being consumed as fast as data is
being generated, routines will block. As a result, CPU utilization may go down,
allowing other processes to run.
`

var NumJobs, NumBlocks int

func RandGen(comm chan io.Reader, quit chan bool) {
	data := make([]byte, aes.BlockSize*NumBlocks)
	for {
		// Create a new encryption cipher with random key
		key := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, key); num != aes.BlockSize {
			panic("Could not seed a random cryptographic key.")
		}
		aesCipher, _ := aes.NewCipher(key)

		// Create a new CBC generator with a random initialization vector
		vector := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, vector); num != aes.BlockSize {
			panic("Could not seed a random initialization vector.")
		}
		cbcCipher := cipher.NewCBCEncrypter(aesCipher, vector)

		// Generate pseudo-random data by encrypting in CBC mode
		cbcCipher.CryptBlocks(data, data)

		// Send data to main routine
		select {
		case comm <- bytes.NewBuffer(data):
			continue
		case <-quit:
			break
		}
	}
}

func main() {
	comm := make(chan io.Reader)
	quit := make(chan bool)

	// Command-line parser
	fs := flag.NewFlagSet("", flag.ExitOnError)
	fs.Usage = func() {
		cmd := path.Base(os.Args[0])
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", cmd)
		fmt.Fprintln(os.Stderr, DESCRIPTION)
		fs.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n")
		fmt.Fprintf(os.Stderr, "Report '%s' bugs to joetsai@digital-static.net\n", cmd)
	}
	fs.IntVar(&NumJobs, "jobs", runtime.NumCPU(), "Number of Go-routines jobs to spin off.")
	fs.IntVar(&NumBlocks, "blocks", (1 << 16), "Each routine will generate this many pseudo-random blocks before re-seeding.")
	fs.Parse(os.Args[1:])
	if NumJobs <= 0 {
		fmt.Fprintln(os.Stderr, "Number of jobs must be positive.")
	}
	if NumBlocks <= 0 {
		fmt.Fprintln(os.Stderr, "Number of blocks to generate must be positive.")
	}

	// Spin off a great number of workers
	runtime.GOMAXPROCS(NumJobs)
	for i := 0; i < NumJobs; i++ {
		go RandGen(comm, quit)
	}

	// Continually read data from workers
	dstBuf := bufio.NewWriter(os.Stdout)
	for {
		srcBuf := <-comm
		if _, err := io.Copy(dstBuf, srcBuf); err != nil {
			close(quit)
			break
		}
	}
}
<|endoftext|>


<commit_before>// gorewind is an event store server written in Python that talks ZeroMQ.
// Copyright (C) 2013  Jens Rantil
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// GoRewind is an event store server written in Go that talks ZeroMQ.
package main

import (
	"flag"
	"fmt"
	"os"
	"github.com/jensrantil/gorewind/server"
	"github.com/syndtr/goleveldb/leveldb/descriptor"
)

var (
	eventStorePath = flag.String("datadir", "data",
	"directory path where incoming events will be stored. Created"+
	" if non-existent.")
	commandSocketZPath = flag.String("commandsocket",
	"tcp://127.0.0.1:9002", "Command socket. Handles new eventsand"+
	" queries.")
	eventPublishZPath = flag.String("evpubsocket",
	"tcp://127.0.0.1:9003", "ZeroMQ event publishing socket.")
)

// Main method. Will panic if things are so bad that the application
// will not start.
func main() {
	flag.Parse()

	desc, err := descriptor.OpenFile(*eventStorePath)
	if err != nil {
		fmt.Fprintln(os.Stderr, "could not create descriptor")
		panic(err)
	}
	defer desc.Close()

	estore, err := server.NewEventStore(desc)
	if err != nil {
		fmt.Fprintln(os.Stderr, "could not create event store")
		panic(err)
	}
	defer estore.Close()

	initParams := server.InitParams{
		Store: estore,
	}
	serv, err := server.New(&initParams)
	if err == nil {
		panic(err.Error())
	}

	// TODO: Handle SIGINT correctly and smoothly.

	serv.Run()
}
<commit_msg>Printing application config settings on startup<commit_after>// gorewind is an event store server written in Python that talks ZeroMQ.
// Copyright (C) 2013  Jens Rantil
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// GoRewind is an event store server written in Go that talks ZeroMQ.
package main

import (
	"flag"
	"fmt"
	"os"
	"github.com/jensrantil/gorewind/server"
	"github.com/syndtr/goleveldb/leveldb/descriptor"
)

var (
	eventStorePath = flag.String("datadir", "data",
	"directory path where incoming events will be stored. Created"+
	" if non-existent.")
	commandSocketZPath = flag.String("commandsocket",
	"tcp://127.0.0.1:9002", "Command socket. Handles new eventsand"+
	" queries.")
	eventPublishZPath = flag.String("evpubsocket",
	"tcp://127.0.0.1:9003", "ZeroMQ event publishing socket.")
)

// Main method. Will panic if things are so bad that the application
// will not start.
func main() {
	flag.Parse()

	// TODO: Use logging framework
	fmt.Println("Event store to use:", *eventStorePath)
	fmt.Println("Command socket path:", *commandSocketZPath)
	fmt.Println("Event publishing socket path:", *eventPublishZPath)
	fmt.Println()

	desc, err := descriptor.OpenFile(*eventStorePath)
	if err != nil {
		fmt.Fprintln(os.Stderr, "could not create descriptor")
		panic(err)
	}
	defer desc.Close()

	estore, err := server.NewEventStore(desc)
	if err != nil {
		fmt.Fprintln(os.Stderr, "could not create event store")
		panic(err)
	}
	defer estore.Close()

	initParams := server.InitParams{
		Store: estore,
	}
	serv, err := server.New(&initParams)
	if err == nil {
		panic(err.Error())
	}

	// TODO: Handle SIGINT correctly and smoothly.

	serv.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"../uatparse"
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Printf("%s <uat log>\n", os.Args[0])
		return
	}
	fp, err := os.Open(os.Args[1])
	if err != nil {
		fmt.Printf("can't open '%s'.\n", os.Args[1])
		return
	}
	defer fp.Close()

	reader := bufio.NewReader(fp)

	for {
		buf, err := reader.ReadString('\n')
		if err != nil {
			fmt.Printf("lost stdin.\n")
			break
		}

		x := strings.Split(buf, ",")

		uatMsg, err := uatparse.New(x[1])
		if err != nil {
			//			fmt.Printf("err %s\n", err.Error())
			continue
		}

		uatMsg.DecodeUplink()

		/*
			p, _ := uatMsg.GetTextReports()
			for _, r := range p {
				fmt.Printf("!!!!%s!!!!\n", r)
			}
		*/

		fmt.Printf("%s,%f,%f,%d,%d, says: ", x[0], uatMsg.Lat, uatMsg.Lon, uatMsg.RS_Err, uatMsg.SignalStrength)
		types := make(map[string]int)
		for _, uatframe := range uatMsg.Frames {
			if uatframe.Product_id == 413 {
				for _, txt := range uatframe.Text_data {
					txt = strings.Trim(txt, " ")
					if len(txt) == 0 {
						continue
					}
					p := strings.Split(txt, " ")
					thisType := p[0]
					types[thisType]++
				}
			} else {
				if uatframe.Frame_type == 0 { // FIS-B product.
					types[strconv.Itoa(int(uatframe.Product_id))]++
				} else {
					types[strconv.Itoa(int(uatframe.Frame_type))]++
				}
			}
		}

		if len(types) == 0 {
			fmt.Printf("(unimplemented)\n")
		} else {
			for thisType, thisNum := range types {
				fmt.Printf("%s(%d) ", thisType, thisNum)
			}
			fmt.Printf("\n")
			//			fmt.Printf("%s\n", buf)
			//			k, _ := uatMsg.GetTextReports()
			//			fmt.Printf("%v\n", k)
		}
	}
}
<commit_msg>Error checking.<commit_after>package main

import (
	"../uatparse"
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Printf("%s <uat log>\n", os.Args[0])
		return
	}
	fp, err := os.Open(os.Args[1])
	if err != nil {
		fmt.Printf("can't open '%s'.\n", os.Args[1])
		return
	}
	defer fp.Close()

	reader := bufio.NewReader(fp)

	for {
		buf, err := reader.ReadString('\n')
		if err != nil {
			fmt.Printf("lost stdin.\n")
			break
		}

		x := strings.Split(buf, ",")

		if len(x) < 2 {
			continue
		}

		uatMsg, err := uatparse.New(x[1])
		if err != nil {
			//			fmt.Printf("err %s\n", err.Error())
			continue
		}

		uatMsg.DecodeUplink()

		/*
			p, _ := uatMsg.GetTextReports()
			for _, r := range p {
				fmt.Printf("!!!!%s!!!!\n", r)
			}
		*/

		fmt.Printf("%s,%f,%f,%d,%d, says: ", x[0], uatMsg.Lat, uatMsg.Lon, uatMsg.RS_Err, uatMsg.SignalStrength)
		types := make(map[string]int)
		for _, uatframe := range uatMsg.Frames {
			if uatframe.Product_id == 413 {
				for _, txt := range uatframe.Text_data {
					txt = strings.Trim(txt, " ")
					if len(txt) == 0 {
						continue
					}
					p := strings.Split(txt, " ")
					thisType := p[0]
					types[thisType]++
				}
			} else {
				if uatframe.Frame_type == 0 { // FIS-B product.
					types[strconv.Itoa(int(uatframe.Product_id))]++
				} else {
					types[strconv.Itoa(int(uatframe.Frame_type))]++
				}
			}
		}

		if len(types) == 0 {
			fmt.Printf("(unimplemented)\n")
		} else {
			for thisType, thisNum := range types {
				fmt.Printf("%s(%d) ", thisType, thisNum)
			}
			fmt.Printf("\n")
			//			fmt.Printf("%s\n", buf)
			//			k, _ := uatMsg.GetTextReports()
			//			fmt.Printf("%v\n", k)
		}
	}
}
<|endoftext|>