<commit_before>// Package md decodes md and smd files.

package md

import (
	"bytes"
	"github.com/sselph/scraper/rom"
	"io"
	"io/ioutil"
)

func init() {
	rom.RegisterFormat(".smd", decodeSMD)
	rom.RegisterFormat(".mgd", decodeMGD)
	rom.RegisterFormat(".gen", rom.Noop)
	rom.RegisterFormat(".md", rom.Noop)
	rom.RegisterFormat(".32x", rom.Noop)
}

func DeInterleave(p []byte) []byte {
	l := len(p)
	m := l / 2
	b := make([]byte, l)
	for i, x := range p {
		if i < m {
			b[i*2+1] = x
		} else {
			b[i*2-l] = x
		}
	}
	return b
}

type SMDReader struct {
	f io.ReadCloser
	b []byte
	r *int
}

func (r SMDReader) Read(p []byte) (int, error) {
	ll := len(p)
	rl := ll - *r.r
	l := rl + 16384 - 1 - (rl-1)%16384
	copy(p, r.b[:*r.r])
	if rl <= 0 {
		*r.r = *r.r - ll
		copy(r.b, r.b[ll:])
		return ll, nil
	}
	n := *r.r
	for i := 0; i < l/16384; i++ {
		b := make([]byte, 16384)
		x, err := io.ReadFull(r.f, b)
		if x == 0 || err != nil {
			return n, err
		}
		b = DeInterleave(b)
		if ll < n+x {
			copy(p[n:ll], b)
			copy(r.b, b[ll-n:])
			*r.r = n + x - ll
			return ll, nil
		} else {
			copy(p[n:n+16384], b)
		}
		n += x
	}
	return ll, nil
}

func (r SMDReader) Close() error {
	return r.f.Close()
}

func decodeSMD(f io.ReadCloser, s int64) (io.ReadCloser, error) {
	tmp := make([]byte, 512)
	_, err := io.ReadFull(f, tmp)
	if err != nil {
		return nil, err
	}
	i := 0
	return SMDReader{f, make([]byte, 16384), &i}, nil
}

type MGDReader struct {
	r io.Reader
}

func (r MGDReader) Read(p []byte) (int, error) {
	n, err := r.r.Read(p)
	return n, err
}

func (r MGDReader) Close() error {
	return nil
}

func decodeMGD(f io.ReadCloser, s int64) (io.ReadCloser, error) {
	b, err := ioutil.ReadAll(f)
	f.Close()
	b = DeInterleave(b)
	if err != nil {
		return nil, err
	}
	return MGDReader{bytes.NewReader(b)}, nil
}
<commit_msg>Add .gg extension<commit_after>// Package md decodes md and smd files.

package md

import (
	"bytes"
	"github.com/sselph/scraper/rom"
	"io"
	"io/ioutil"
)

func init() {
	rom.RegisterFormat(".smd", decodeSMD)
	rom.RegisterFormat(".mgd", decodeMGD)
	rom.RegisterFormat(".gen", rom.Noop)
	rom.RegisterFormat(".md", rom.Noop)
	rom.RegisterFormat(".32x", rom.Noop)
	rom.RegisterFormat(".gg", rom.Noop)
}

func DeInterleave(p []byte) []byte {
	l := len(p)
	m := l / 2
	b := make([]byte, l)
	for i, x := range p {
		if i < m {
			b[i*2+1] = x
		} else {
			b[i*2-l] = x
		}
	}
	return b
}

type SMDReader struct {
	f io.ReadCloser
	b []byte
	r *int
}

func (r SMDReader) Read(p []byte) (int, error) {
	ll := len(p)
	rl := ll - *r.r
	l := rl + 16384 - 1 - (rl-1)%16384
	copy(p, r.b[:*r.r])
	if rl <= 0 {
		*r.r = *r.r - ll
		copy(r.b, r.b[ll:])
		return ll, nil
	}
	n := *r.r
	for i := 0; i < l/16384; i++ {
		b := make([]byte, 16384)
		x, err := io.ReadFull(r.f, b)
		if x == 0 || err != nil {
			return n, err
		}
		b = DeInterleave(b)
		if ll < n+x {
			copy(p[n:ll], b)
			copy(r.b, b[ll-n:])
			*r.r = n + x - ll
			return ll, nil
		} else {
			copy(p[n:n+16384], b)
		}
		n += x
	}
	return ll, nil
}

func (r SMDReader) Close() error {
	return r.f.Close()
}

func decodeSMD(f io.ReadCloser, s int64) (io.ReadCloser, error) {
	tmp := make([]byte, 512)
	_, err := io.ReadFull(f, tmp)
	if err != nil {
		return nil, err
	}
	i := 0
	return SMDReader{f, make([]byte, 16384), &i}, nil
}

type MGDReader struct {
	r io.Reader
}

func (r MGDReader) Read(p []byte) (int, error) {
	n, err := r.r.Read(p)
	return n, err
}

func (r MGDReader) Close() error {
	return nil
}

func decodeMGD(f io.ReadCloser, s int64) (io.ReadCloser, error) {
	b, err := ioutil.ReadAll(f)
	f.Close()
	b = DeInterleave(b)
	if err != nil {
		return nil, err
	}
	return MGDReader{bytes.NewReader(b)}, nil
}
<|endoftext|>


<commit_before>package apexovernsq

import (
	"fmt"
	"testing"

	"github.com/avct/apexovernsq/protobuf"

	alog "github.com/apex/log"
	"github.com/apex/log/handlers/memory"
	nsq "github.com/nsqio/go-nsq"
)

type entryList []*alog.Entry

// simulateMessageFromNSQ packs an Apex Log Entry into an NSQ Message
// and pushes it through the NSQApexLogHandler.  The NSQApexLogHandler
// will use the Apex Log memory handler to return the Apex Log Entry
// that would be logged.
func simulateMessageFromNSQ(sourceEntry *alog.Entry, filter *[]string) (*alog.Entry, error) {
	var handler *NSQApexLogHandler
	marshalledEntry, err := protobuf.Marshal(sourceEntry)
	if err != nil {
		return nil, fmt.Errorf("Couldn't marshal log entry: %s", err.Error())
	}

	msg := nsq.NewMessage(nsq.MessageID{'a', 'b', 'c'}, []byte(marshalledEntry))

	innerHandler := memory.New()
	if filter == nil {
		handler = NewNSQApexLogHandler(innerHandler, protobuf.Unmarshal)
	} else {
		filterHandler := NewApexLogServiceFilterHandler(innerHandler, filter)
		handler = NewNSQApexLogHandler(filterHandler, protobuf.Unmarshal)
	}

	handler.HandleMessage(msg)
	return innerHandler.Entries[0], nil
}

// simulateMessagesFromNSQ packs an entryList into a series of NSQ Messages and pushes them through the NSQApexLogHandler.  The NSQApexLogHandler will use the Apex Log memory handler to return an entryList that would be logged locally.
func simulateMessagesFromNSQ(sourceEntries *entryList, filter *[]string) (*entryList, error) {
	var marshalledEntry []byte
	var err error
	var msg *nsq.Message
	var handler nsq.Handler

	innerHandler := memory.New()
	if filter == nil {
		handler = NewNSQApexLogHandler(innerHandler, protobuf.Unmarshal)
	} else {
		filterHandler := NewApexLogServiceFilterHandler(innerHandler, filter)
		handler = NewNSQApexLogHandler(filterHandler, protobuf.Unmarshal)
	}

	for _, sourceEntry := range *sourceEntries {
		marshalledEntry, err = protobuf.Marshal(sourceEntry)
		if err != nil {
			return nil, fmt.Errorf("Couldn't marshal log entry: %s", err.Error())
		}

		msg = nsq.NewMessage(nsq.MessageID{'a', 'b', 'c'}, marshalledEntry)
		handler.HandleMessage(msg)
	}
	result := innerHandler.Entries[:]
	return (*entryList)(&result), nil

}

// simulateEntry returns a finalised Entry from the memory handler as
// it would appear in normal logging.
func simulateEntry(logger alog.Interface, fields alog.Fielder, msg string) *alog.Entry {
	memoryHandler := memory.New()
	alog.SetHandler(memoryHandler)
	if fields == nil {
		logger.Info(msg)
	} else {
		logger.WithFields(fields).Info(msg)
	}
	return memoryHandler.Entries[0]
}

// simulateEntries makes a stipulated number of finalised Apex Log
// Entry instances and stores them in a provided store (a pointer to
// an entryList), starting from a given offset. ⚠ Danger Will
// Robinson, here be side-effects. The provided offset and store will
// both be mutated. ⚠
func simulateEntries(ctx alog.Interface, count int, offset *int, store *entryList) {
	var m int
	for m = 0; m < count; m++ {
		entry := simulateEntry(ctx, nil, fmt.Sprintf("%d", *offset))
		(*store)[*offset] = entry
		*offset++
	}
}

func TestHandleMessage(t *testing.T) {
	logger := alog.Log
	sourceEntry := simulateEntry(logger, alog.Fields{
		"flavour": "pistachio",
		"scoops":  "2",
	}, "it's ice cream time!")

	entry, err := simulateMessageFromNSQ(sourceEntry, nil)
	if err != nil {
		t.Fatalf("%s", err.Error())
	}
	if entry.Message != sourceEntry.Message {
		t.Errorf("Expected %q, got %q", sourceEntry.Message, entry.Message)
	}
	if entry.Level != sourceEntry.Level {
		t.Errorf("Expected %s, got %s", sourceEntry.Level, entry.Level)
	}
	if entry.Timestamp != sourceEntry.Timestamp {
		t.Errorf("Expected %q, got %q", sourceEntry.Timestamp, entry.Timestamp)
	}
	expectedFieldCount := len(sourceEntry.Fields)
	actualFieldCount := len(entry.Fields)
	if expectedFieldCount != actualFieldCount {
		t.Errorf("Expected %d fields, but got %d fields", expectedFieldCount, actualFieldCount)
	}
	for fieldName, value := range sourceEntry.Fields {
		recieved := entry.Fields.Get(fieldName)
		if recieved != value {
			t.Errorf("Expected %s=%q, got %s=%q", fieldName, value, fieldName, recieved)
		}
	}
}

func TestFilterMessagesByService(t *testing.T) {
	var ctx alog.Interface
	var entries *entryList
	var err error
	var generatedMessages int
	var resultEntryCount int
	var sourceEntries entryList
	var totalMessages int

	var thisProcessFilter = &[]string{processName()}
	var otherProcessFilter = &[]string{"other"}
	var unknownProcessFilter = &[]string{"unknown"}

	var caseTable = []struct {
		serviceMessages      int
		otherServiceMessages int
		nonServiceMessages   int
		resultEntryCount     int
		filter               *[]string
		messages             []string
	}{
		{1, 1, 1, 3, nil, []string{"0", "1", "2"}},      // Default case, no filtering
		{1, 1, 1, 1, thisProcessFilter, []string{"0"}},  // Whitelist service messages
		{1, 1, 1, 1, otherProcessFilter, []string{"1"}}, // Whitelist other service messages
		{1, 1, 1, 0, unknownProcessFilter, []string{}},  // Whitelist service that isn't present

	}

	for caseNum, testCase := range caseTable {
		totalMessages = testCase.serviceMessages + testCase.nonServiceMessages + testCase.otherServiceMessages
		generatedMessages = 0
		sourceEntries = make([]*alog.Entry, totalMessages)

		// Generate service messages
		ctx = NewApexLogServiceContext()
		simulateEntries(ctx, testCase.serviceMessages, &generatedMessages, &sourceEntries)
		// Generate other service messages
		ctx = ctx.WithFields(alog.Fields{"service": "other"})
		simulateEntries(ctx, testCase.otherServiceMessages, &generatedMessages, &sourceEntries)

		// Generate non-service messages
		ctx = alog.Log
		simulateEntries(ctx, testCase.nonServiceMessages, &generatedMessages, &sourceEntries)

		entries, err = simulateMessagesFromNSQ(&sourceEntries, testCase.filter)
		if err != nil {
			t.Fatalf("Error in message simulation: %s", err.Error())
		}
		if entries == nil && testCase.resultEntryCount > 0 {
			t.Errorf("Expected %d entries from test case %d but got nil. Message counts: service %d, other-service %d, non-service %d.  Filter: %+v.", testCase.resultEntryCount, caseNum, testCase.serviceMessages, testCase.otherServiceMessages, testCase.nonServiceMessages, testCase.filter)
			continue
		}
		resultEntryCount = len(*entries)
		if resultEntryCount != testCase.resultEntryCount {
			t.Errorf("[Case %d] Expected %d entries, but got %d. Message counts: service %d, other-service %d, non-service %d.  Filter: %+v.", caseNum+1, testCase.resultEntryCount, resultEntryCount, testCase.serviceMessages, testCase.otherServiceMessages, testCase.nonServiceMessages, testCase.filter)
			continue
		}

		for idx, entry := range *entries {
			testMessage := testCase.messages[idx]
			if entry.Message != testMessage {
				t.Errorf("[Case %d] Expected Entry[%d] to have message %q, but got %q", caseNum, idx, testMessage, entry.Message)
			}
		}
	}
}
<commit_msg>Test multi-service filtering<commit_after>package apexovernsq

import (
	"fmt"
	"testing"

	"github.com/avct/apexovernsq/protobuf"

	alog "github.com/apex/log"
	"github.com/apex/log/handlers/memory"
	nsq "github.com/nsqio/go-nsq"
)

type entryList []*alog.Entry

// simulateMessageFromNSQ packs an Apex Log Entry into an NSQ Message
// and pushes it through the NSQApexLogHandler.  The NSQApexLogHandler
// will use the Apex Log memory handler to return the Apex Log Entry
// that would be logged.
func simulateMessageFromNSQ(sourceEntry *alog.Entry, filter *[]string) (*alog.Entry, error) {
	var handler *NSQApexLogHandler
	marshalledEntry, err := protobuf.Marshal(sourceEntry)
	if err != nil {
		return nil, fmt.Errorf("Couldn't marshal log entry: %s", err.Error())
	}

	msg := nsq.NewMessage(nsq.MessageID{'a', 'b', 'c'}, []byte(marshalledEntry))

	innerHandler := memory.New()
	if filter == nil {
		handler = NewNSQApexLogHandler(innerHandler, protobuf.Unmarshal)
	} else {
		filterHandler := NewApexLogServiceFilterHandler(innerHandler, filter)
		handler = NewNSQApexLogHandler(filterHandler, protobuf.Unmarshal)
	}

	handler.HandleMessage(msg)
	return innerHandler.Entries[0], nil
}

// simulateMessagesFromNSQ packs an entryList into a series of NSQ Messages and pushes them through the NSQApexLogHandler.  The NSQApexLogHandler will use the Apex Log memory handler to return an entryList that would be logged locally.
func simulateMessagesFromNSQ(sourceEntries *entryList, filter *[]string) (*entryList, error) {
	var marshalledEntry []byte
	var err error
	var msg *nsq.Message
	var handler nsq.Handler

	innerHandler := memory.New()
	if filter == nil {
		handler = NewNSQApexLogHandler(innerHandler, protobuf.Unmarshal)
	} else {
		filterHandler := NewApexLogServiceFilterHandler(innerHandler, filter)
		handler = NewNSQApexLogHandler(filterHandler, protobuf.Unmarshal)
	}

	for _, sourceEntry := range *sourceEntries {
		marshalledEntry, err = protobuf.Marshal(sourceEntry)
		if err != nil {
			return nil, fmt.Errorf("Couldn't marshal log entry: %s", err.Error())
		}

		msg = nsq.NewMessage(nsq.MessageID{'a', 'b', 'c'}, marshalledEntry)
		handler.HandleMessage(msg)
	}
	result := innerHandler.Entries[:]
	return (*entryList)(&result), nil

}

// simulateEntry returns a finalised Entry from the memory handler as
// it would appear in normal logging.
func simulateEntry(logger alog.Interface, fields alog.Fielder, msg string) *alog.Entry {
	memoryHandler := memory.New()
	alog.SetHandler(memoryHandler)
	if fields == nil {
		logger.Info(msg)
	} else {
		logger.WithFields(fields).Info(msg)
	}
	return memoryHandler.Entries[0]
}

// simulateEntries makes a stipulated number of finalised Apex Log
// Entry instances and stores them in a provided store (a pointer to
// an entryList), starting from a given offset. ⚠ Danger Will
// Robinson, here be side-effects. The provided offset and store will
// both be mutated. ⚠
func simulateEntries(ctx alog.Interface, count int, offset *int, store *entryList) {
	var m int
	for m = 0; m < count; m++ {
		entry := simulateEntry(ctx, nil, fmt.Sprintf("%d", *offset))
		(*store)[*offset] = entry
		*offset++
	}
}

func TestHandleMessage(t *testing.T) {
	logger := alog.Log
	sourceEntry := simulateEntry(logger, alog.Fields{
		"flavour": "pistachio",
		"scoops":  "2",
	}, "it's ice cream time!")

	entry, err := simulateMessageFromNSQ(sourceEntry, nil)
	if err != nil {
		t.Fatalf("%s", err.Error())
	}
	if entry.Message != sourceEntry.Message {
		t.Errorf("Expected %q, got %q", sourceEntry.Message, entry.Message)
	}
	if entry.Level != sourceEntry.Level {
		t.Errorf("Expected %s, got %s", sourceEntry.Level, entry.Level)
	}
	if entry.Timestamp != sourceEntry.Timestamp {
		t.Errorf("Expected %q, got %q", sourceEntry.Timestamp, entry.Timestamp)
	}
	expectedFieldCount := len(sourceEntry.Fields)
	actualFieldCount := len(entry.Fields)
	if expectedFieldCount != actualFieldCount {
		t.Errorf("Expected %d fields, but got %d fields", expectedFieldCount, actualFieldCount)
	}
	for fieldName, value := range sourceEntry.Fields {
		recieved := entry.Fields.Get(fieldName)
		if recieved != value {
			t.Errorf("Expected %s=%q, got %s=%q", fieldName, value, fieldName, recieved)
		}
	}
}

func TestFilterMessagesByService(t *testing.T) {
	var ctx alog.Interface
	var entries *entryList
	var err error
	var generatedMessages int
	var resultEntryCount int
	var sourceEntries entryList
	var totalMessages int

	var thisProcessFilter = &[]string{processName()}
	var otherProcessFilter = &[]string{"other"}
	var unknownProcessFilter = &[]string{"unknown"}
	var multiServiceFilter = &[]string{processName(), "other"}

	var caseTable = []struct {
		serviceMessages      int
		otherServiceMessages int
		nonServiceMessages   int
		resultEntryCount     int
		filter               *[]string
		messages             []string
	}{
		{1, 1, 1, 3, nil, []string{"0", "1", "2"}},           // Default case, no filtering
		{1, 1, 1, 1, thisProcessFilter, []string{"0"}},       // Whitelist service messages
		{1, 1, 1, 1, otherProcessFilter, []string{"1"}},      // Whitelist other service messages
		{1, 1, 1, 0, unknownProcessFilter, []string{}},       // Whitelist service that isn't present
		{1, 1, 1, 2, multiServiceFilter, []string{"0", "1"}}, // Whitelist both this service and "other" service

	}

	for caseNum, testCase := range caseTable {
		totalMessages = testCase.serviceMessages + testCase.nonServiceMessages + testCase.otherServiceMessages
		generatedMessages = 0
		sourceEntries = make([]*alog.Entry, totalMessages)

		// Generate service messages
		ctx = NewApexLogServiceContext()
		simulateEntries(ctx, testCase.serviceMessages, &generatedMessages, &sourceEntries)
		// Generate other service messages
		ctx = ctx.WithFields(alog.Fields{"service": "other"})
		simulateEntries(ctx, testCase.otherServiceMessages, &generatedMessages, &sourceEntries)

		// Generate non-service messages
		ctx = alog.Log
		simulateEntries(ctx, testCase.nonServiceMessages, &generatedMessages, &sourceEntries)

		entries, err = simulateMessagesFromNSQ(&sourceEntries, testCase.filter)
		if err != nil {
			t.Fatalf("Error in message simulation: %s", err.Error())
		}
		if entries == nil && testCase.resultEntryCount > 0 {
			t.Errorf("Expected %d entries from test case %d but got nil. Message counts: service %d, other-service %d, non-service %d.  Filter: %+v.", testCase.resultEntryCount, caseNum, testCase.serviceMessages, testCase.otherServiceMessages, testCase.nonServiceMessages, testCase.filter)
			continue
		}
		resultEntryCount = len(*entries)
		if resultEntryCount != testCase.resultEntryCount {
			t.Errorf("[Case %d] Expected %d entries, but got %d. Message counts: service %d, other-service %d, non-service %d.  Filter: %+v.", caseNum+1, testCase.resultEntryCount, resultEntryCount, testCase.serviceMessages, testCase.otherServiceMessages, testCase.nonServiceMessages, testCase.filter)
			continue
		}

		for idx, entry := range *entries {
			testMessage := testCase.messages[idx]
			if entry.Message != testMessage {
				t.Errorf("[Case %d] Expected Entry[%d] to have message %q, but got %q", caseNum, idx, testMessage, entry.Message)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/kbrebanov/nose-bleed/parser"

	"github.com/google/gopacket"
	"github.com/google/gopacket/pcap"
	"github.com/streadway/amqp"
)

const version string = "0.1.0"

// RabbitMQSettings is a structure for RabbitMQ settings
type RabbitMQSettings struct {
	User         string `json:"user"`
	Password     string `json:"password"`
	Host         string `json:"host"`
	Port         int    `json:"port"`
	Exchange     string `json:"exchange"`
	ExchangeType string `json:"exchange_type"`
}

// Settings is a structure for configuration settings
type Settings struct {
	RabbitMQ RabbitMQSettings `json:"rabbitmq,omitempty"`
}

// RabbitMQ error handler
func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
	}
}

// sniff starts a live capture of network packets, parses and outputs
// the JSON results to either standard output or a RabbitMQ exchange.
func sniff(deviceName string, snapshotLen int32, promiscuous bool, timeout time.Duration,
	filter string, settings *Settings) {

	var ch *amqp.Channel

	useRabbitMQ := false

	if settings.RabbitMQ.User != "" && settings.RabbitMQ.Password != "" && settings.RabbitMQ.Host != "" &&
		settings.RabbitMQ.Exchange != "" && settings.RabbitMQ.ExchangeType != "" {
		useRabbitMQ = true
	}

	// Initialize msg queue
	if useRabbitMQ {
		conn, err := amqp.Dial(fmt.Sprintf("amqp://%s:%s@%s/", settings.RabbitMQ.User, settings.RabbitMQ.Password, fmt.Sprintf("%s:%d", settings.RabbitMQ.Host, settings.RabbitMQ.Port)))
		failOnError(err, "Failed to connect to RabbitMQ")
		defer conn.Close()

		// Create a channel
		ch, err = conn.Channel()
		failOnError(err, "Failed to open a channel")
		defer ch.Close()

		// Declare an exchange
		err = ch.ExchangeDeclare(settings.RabbitMQ.Exchange, settings.RabbitMQ.ExchangeType, true, false, false, false, nil)
		failOnError(err, "Failed to declare an exchange")
	}

	// Start a live capture
	handle, err := pcap.OpenLive(deviceName, snapshotLen, promiscuous, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	// Set filter
	if filter != "" {
		err = handle.SetBPFFilter(filter)
		if err != nil {
			log.Println(err)
		}
	}

	// Parse each packet
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
		headers, err := parser.Parse(packet)
		if err != nil {
			log.Println(err)
		}

		if useRabbitMQ {
			b, err := json.Marshal(headers)
			if err != nil {
				log.Println(err)
				// Skip packet if JSON marshalling errors
				continue
			}
			// Send JSON to RabbitMQ exchange
			err = ch.Publish(settings.RabbitMQ.Exchange, "", false, false, amqp.Publishing{
				ContentType: "text/json",
				Body:        b,
			})
			failOnError(err, "Failed to publish a message")
		} else {
			// Pretty print JSON when sending to standard output
			b, err := json.MarshalIndent(headers, "", "  ")
			if err != nil {
				log.Println(err)
				// Skip packet if JSON marshalling errors
				continue
			}
			fmt.Println(string(b))
			fmt.Println()
		}
	}
}

func main() {
	// Set command line flags
	device := flag.String("device", "eth0", "Device to sniff")
	snaplen := flag.Int("snaplen", 65535, "Snapshot length")
	promiscuous := flag.Bool("promiscuous", false, "Set promiscuous mode")
	timeout := flag.Duration("timeout", 30*time.Second, "Timeout")
	filter := flag.String("filter", "", "Berkley Packet Filter (BPF)")
	showVersion := flag.Bool("version", false, "Show version")
	logFilePath := flag.String("log", "./nose-bleed.log", "Path to log file")
	configPath := flag.String("config", "", "Path to configuration file in JSON format")

	flag.Parse()

	// Show version and exit if version flag is set
	if *showVersion {
		fmt.Println(version)
		os.Exit(0)
	}

	// Configure logging
	logFile, err := os.OpenFile(*logFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer logFile.Close()
	log.SetOutput(logFile)

	// Get settings
	settings := new(Settings)
	if *configPath != "" {
		s, err := ioutil.ReadFile(*configPath)
		if err != nil {
			log.Fatal(err)
		}

		if err := json.Unmarshal(s, settings); err != nil {
			log.Fatal(err)
		}
	}

	// Start sniffing
	sniff(*device, int32(*snaplen), *promiscuous, *timeout, *filter, settings)

}
<commit_msg>Cast snapshot length to int32 when starting capture<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/kbrebanov/nose-bleed/parser"

	"github.com/google/gopacket"
	"github.com/google/gopacket/pcap"
	"github.com/streadway/amqp"
)

const version string = "0.1.0"

// RabbitMQSettings is a structure for RabbitMQ settings
type RabbitMQSettings struct {
	User         string `json:"user"`
	Password     string `json:"password"`
	Host         string `json:"host"`
	Port         int    `json:"port"`
	Exchange     string `json:"exchange"`
	ExchangeType string `json:"exchange_type"`
}

// Settings is a structure for configuration settings
type Settings struct {
	RabbitMQ RabbitMQSettings `json:"rabbitmq,omitempty"`
}

// RabbitMQ error handler
func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
	}
}

// sniff starts a live capture of network packets, parses and outputs
// the JSON results to either standard output or a RabbitMQ exchange.
func sniff(deviceName string, snapshotLen int, promiscuous bool, timeout time.Duration,
	filter string, settings *Settings) {

	var ch *amqp.Channel

	useRabbitMQ := false

	if settings.RabbitMQ.User != "" && settings.RabbitMQ.Password != "" && settings.RabbitMQ.Host != "" &&
		settings.RabbitMQ.Exchange != "" && settings.RabbitMQ.ExchangeType != "" {
		useRabbitMQ = true
	}

	// Initialize msg queue
	if useRabbitMQ {
		conn, err := amqp.Dial(fmt.Sprintf("amqp://%s:%s@%s/", settings.RabbitMQ.User, settings.RabbitMQ.Password, fmt.Sprintf("%s:%d", settings.RabbitMQ.Host, settings.RabbitMQ.Port)))
		failOnError(err, "Failed to connect to RabbitMQ")
		defer conn.Close()

		// Create a channel
		ch, err = conn.Channel()
		failOnError(err, "Failed to open a channel")
		defer ch.Close()

		// Declare an exchange
		err = ch.ExchangeDeclare(settings.RabbitMQ.Exchange, settings.RabbitMQ.ExchangeType, true, false, false, false, nil)
		failOnError(err, "Failed to declare an exchange")
	}

	// Start a live capture
	handle, err := pcap.OpenLive(deviceName, int32(snapshotLen), promiscuous, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	// Set filter
	if filter != "" {
		err = handle.SetBPFFilter(filter)
		if err != nil {
			log.Println(err)
		}
	}

	// Parse each packet
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
		headers, err := parser.Parse(packet)
		if err != nil {
			log.Println(err)
		}

		if useRabbitMQ {
			b, err := json.Marshal(headers)
			if err != nil {
				log.Println(err)
				// Skip packet if JSON marshalling errors
				continue
			}
			// Send JSON to RabbitMQ exchange
			err = ch.Publish(settings.RabbitMQ.Exchange, "", false, false, amqp.Publishing{
				ContentType: "text/json",
				Body:        b,
			})
			failOnError(err, "Failed to publish a message")
		} else {
			// Pretty print JSON when sending to standard output
			b, err := json.MarshalIndent(headers, "", "  ")
			if err != nil {
				log.Println(err)
				// Skip packet if JSON marshalling errors
				continue
			}
			fmt.Println(string(b))
			fmt.Println()
		}
	}
}

func main() {
	// Set command line flags
	device := flag.String("device", "eth0", "Device to sniff")
	snaplen := flag.Int("snaplen", 65535, "Snapshot length")
	promiscuous := flag.Bool("promiscuous", false, "Set promiscuous mode")
	timeout := flag.Duration("timeout", 30*time.Second, "Timeout")
	filter := flag.String("filter", "", "Berkley Packet Filter (BPF)")
	showVersion := flag.Bool("version", false, "Show version")
	logFilePath := flag.String("log", "./nose-bleed.log", "Path to log file")
	configPath := flag.String("config", "", "Path to configuration file in JSON format")

	flag.Parse()

	// Show version and exit if version flag is set
	if *showVersion {
		fmt.Println(version)
		os.Exit(0)
	}

	// Configure logging
	logFile, err := os.OpenFile(*logFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer logFile.Close()
	log.SetOutput(logFile)

	// Get settings
	settings := new(Settings)
	if *configPath != "" {
		s, err := ioutil.ReadFile(*configPath)
		if err != nil {
			log.Fatal(err)
		}

		if err := json.Unmarshal(s, settings); err != nil {
			log.Fatal(err)
		}
	}

	// Start sniffing
	sniff(*device, *snaplen, *promiscuous, *timeout, *filter, settings)

}
<|endoftext|>


<commit_before>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
)

/*
 * Helpers for building runtime.
 */

// mkzversion writes zversion.go:
//
//	package runtime
//	const defaultGoroot = <goroot>
//	const theVersion = <version>
//
func mkzversion(dir, file string) {
	out := fmt.Sprintf(
		"// auto generated by go tool dist\n"+
			"\n"+
			"package runtime\n"+
			"\n"+
			"const defaultGoroot = `%s`\n"+
			"const theVersion = `%s`\n"+
			"const goexperiment = `%s`\n"+
			"var buildVersion = theVersion\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"))

	writefile(out, file, 0)
}

// mkzbootstrap writes cmd/internal/obj/zbootstrap.go:
//
//	package obj
//
//	const defaultGOROOT = <goroot>
//	const defaultGOARM = <goarm>
//	const defaultGOOS = <goos>
//	const defaultGOARCH = <goarch>
//	const version = <version>
//	const goexperiment = <goexperiment>
//
func mkzbootstrap(file string) {
	out := fmt.Sprintf(
		"// auto generated by go tool dist\n"+
			"\n"+
			"package obj\n"+
			"\n"+
			"const defaultGOROOT = `%s`\n"+
			"const defaultGOARM = `%s`\n"+
			"const defaultGOOS = `%s`\n"+
			"const defaultGOARCH = `%s`\n"+
			"const version = `%s`\n"+
			"const goexperiment = `%s`\n",
		goroot_final, goarm, gohostos, gohostarch, findgoversion(), os.Getenv("GOEXPERIMENT"))

	writefile(out, file, 0)
}
<commit_msg>[dev.cc] cmd/dist: write default GO386 for cmd/internal/obj<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
)

/*
 * Helpers for building runtime.
 */

// mkzversion writes zversion.go:
//
//	package runtime
//	const defaultGoroot = <goroot>
//	const theVersion = <version>
//
func mkzversion(dir, file string) {
	out := fmt.Sprintf(
		"// auto generated by go tool dist\n"+
			"\n"+
			"package runtime\n"+
			"\n"+
			"const defaultGoroot = `%s`\n"+
			"const theVersion = `%s`\n"+
			"const goexperiment = `%s`\n"+
			"var buildVersion = theVersion\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"))

	writefile(out, file, 0)
}

// mkzbootstrap writes cmd/internal/obj/zbootstrap.go:
//
//	package obj
//
//	const defaultGOROOT = <goroot>
//	const defaultGO386 = <go386>
//	const defaultGOARM = <goarm>
//	const defaultGOOS = <goos>
//	const defaultGOARCH = <goarch>
//	const version = <version>
//	const goexperiment = <goexperiment>
//
func mkzbootstrap(file string) {
	out := fmt.Sprintf(
		"// auto generated by go tool dist\n"+
			"\n"+
			"package obj\n"+
			"\n"+
			"const defaultGOROOT = `%s`\n"+
			"const defaultGO386 = `%s`\n"+
			"const defaultGOARM = `%s`\n"+
			"const defaultGOOS = `%s`\n"+
			"const defaultGOARCH = `%s`\n"+
			"const version = `%s`\n"+
			"const goexperiment = `%s`\n",
		goroot_final, go386, goarm, gohostos, gohostarch, findgoversion(), os.Getenv("GOEXPERIMENT"))

	writefile(out, file, 0)
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"ebnf"
	"flag"
	"fmt"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
)

var fset = token.NewFileSet()
var start = flag.String("start", "Start", "name of start production")

func usage() {
	fmt.Fprintf(os.Stderr, "usage: ebnflint [flags] [filename]\n")
	flag.PrintDefaults()
	os.Exit(1)
}

// Markers around EBNF sections in .html files
var (
	open  = []byte(`<pre class="ebnf">`)
	close = []byte(`</pre>`)
)

func extractEBNF(src []byte) []byte {
	var buf bytes.Buffer

	for {
		// i = beginning of EBNF text
		i := bytes.Index(src, open)
		if i < 0 {
			break // no EBNF found - we are done
		}
		i += len(open)

		// write as many newlines as found in the excluded text
		// to maintain correct line numbers in error messages
		for _, ch := range src[0:i] {
			if ch == '\n' {
				buf.WriteByte('\n')
			}
		}

		// j = end of EBNF text (or end of source)
		j := bytes.Index(src[i:], close) // close marker
		if j < 0 {
			j = len(src) - i
		}
		j += i

		// copy EBNF text
		buf.Write(src[i:j])

		// advance
		src = src[j:]
	}

	return buf.Bytes()
}

func main() {
	flag.Parse()

	var filename string
	switch flag.NArg() {
	case 0:
		filename = "/dev/stdin"
	case 1:
		filename = flag.Arg(0)
	default:
		usage()
	}

	src, err := ioutil.ReadFile(filename)
	if err != nil {
		scanner.PrintError(os.Stderr, err)
		os.Exit(1)
	}

	if filepath.Ext(filename) == ".html" {
		src = extractEBNF(src)
	}

	grammar, err := ebnf.Parse(fset, filename, src)
	if err != nil {
		scanner.PrintError(os.Stderr, err)
		os.Exit(1)
	}

	if err = ebnf.Verify(fset, grammar, *start); err != nil {
		scanner.PrintError(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>ebnflint: better handling of stdin<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"ebnf"
	"flag"
	"fmt"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
)

var fset = token.NewFileSet()
var start = flag.String("start", "Start", "name of start production")

func usage() {
	fmt.Fprintf(os.Stderr, "usage: ebnflint [flags] [filename]\n")
	flag.PrintDefaults()
	os.Exit(1)
}

// Markers around EBNF sections in .html files
var (
	open  = []byte(`<pre class="ebnf">`)
	close = []byte(`</pre>`)
)

func report(err os.Error) {
	scanner.PrintError(os.Stderr, err)
	os.Exit(1)
}

func extractEBNF(src []byte) []byte {
	var buf bytes.Buffer

	for {
		// i = beginning of EBNF text
		i := bytes.Index(src, open)
		if i < 0 {
			break // no EBNF found - we are done
		}
		i += len(open)

		// write as many newlines as found in the excluded text
		// to maintain correct line numbers in error messages
		for _, ch := range src[0:i] {
			if ch == '\n' {
				buf.WriteByte('\n')
			}
		}

		// j = end of EBNF text (or end of source)
		j := bytes.Index(src[i:], close) // close marker
		if j < 0 {
			j = len(src) - i
		}
		j += i

		// copy EBNF text
		buf.Write(src[i:j])

		// advance
		src = src[j:]
	}

	return buf.Bytes()
}

func main() {
	flag.Parse()

	var (
		filename string
		src      []byte
		err      os.Error
	)
	switch flag.NArg() {
	case 0:
		filename = "<stdin>"
		src, err = ioutil.ReadAll(os.Stdin)
	case 1:
		filename = flag.Arg(0)
		src, err = ioutil.ReadFile(filename)
	default:
		usage()
	}
	if err != nil {
		report(err)
	}

	if filepath.Ext(filename) == ".html" || bytes.Index(src, open) >= 0 {
		src = extractEBNF(src)
	}

	grammar, err := ebnf.Parse(fset, filename, src)
	if err != nil {
		report(err)
	}

	if err = ebnf.Verify(fset, grammar, *start); err != nil {
		report(err)
	}
}
<|endoftext|>


<commit_before>package storage

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"reflect"
)

type logger interface {
	Println(message string)
}

type StateBootstrap struct {
	logger     logger
	bblVersion string
}

func NewStateBootstrap(logger logger, bblVersion string) StateBootstrap {
	return StateBootstrap{
		logger:     logger,
		bblVersion: bblVersion,
	}
}

func (b StateBootstrap) GetState(dir string) (State, error) {
	state := State{}

	_, err := os.Stat(dir)
	if err != nil {
		return state, err
	}

	file, err := os.Open(filepath.Join(dir, StateFileName))
	if err != nil {
		if os.IsNotExist(err) {
			return state, nil
		}
		return state, err
	}

	err = json.NewDecoder(file).Decode(&state)
	if err != nil {
		return state, err
	}

	emptyState := State{}
	if reflect.DeepEqual(state, emptyState) {
		state = State{
			Version:    STATE_SCHEMA,
			BBLVersion: b.bblVersion,
		}
	} else {
		if state.BBLVersion == "" {
			state.BBLVersion = b.getBBLVersion(state.Version)
		}
	}

	if state.Version < 3 {
		return state, errors.New("Existing bbl environment is incompatible with bbl v3. Create a new environment with v3 to continue.")
	}

	if state.Version > STATE_SCHEMA {
		return state, fmt.Errorf("Existing bbl environment was created with a newer version of bbl. Please upgrade to bbl v%s.\n", state.BBLVersion)
	}

	return state, nil
}

// Get the earliest bbl version compatible with the given bbl state version.
func (b StateBootstrap) getBBLVersion(stateSchema int) string {
	stateToBBLVersion := map[int]string{
		3:  "3.0.0",
		5:  "4.0.0",
		6:  "4.0.0",
		7:  "4.0.0",
		8:  "4.0.0",
		9:  "4.4.0",
		10: "4.6.0",
		11: "5.1.0",
		12: "5.1.0",
		13: "5.4.0",
	}
	bblVersion, ok := stateToBBLVersion[stateSchema]
	if ok {
		return bblVersion
	}
	return "dev"
}
<commit_msg>Map bbl schema version 14 to bbl cli version 6.0.0<commit_after>package storage

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"reflect"
)

type logger interface {
	Println(message string)
}

type StateBootstrap struct {
	logger     logger
	bblVersion string
}

func NewStateBootstrap(logger logger, bblVersion string) StateBootstrap {
	return StateBootstrap{
		logger:     logger,
		bblVersion: bblVersion,
	}
}

func (b StateBootstrap) GetState(dir string) (State, error) {
	state := State{}

	_, err := os.Stat(dir)
	if err != nil {
		return state, err
	}

	file, err := os.Open(filepath.Join(dir, StateFileName))
	if err != nil {
		if os.IsNotExist(err) {
			return state, nil
		}
		return state, err
	}

	err = json.NewDecoder(file).Decode(&state)
	if err != nil {
		return state, err
	}

	emptyState := State{}
	if reflect.DeepEqual(state, emptyState) {
		state = State{
			Version:    STATE_SCHEMA,
			BBLVersion: b.bblVersion,
		}
	} else {
		if state.BBLVersion == "" {
			state.BBLVersion = b.getBBLVersion(state.Version)
		}
	}

	if state.Version < 3 {
		return state, errors.New("Existing bbl environment is incompatible with bbl v3. Create a new environment with v3 to continue.")
	}

	if state.Version > STATE_SCHEMA {
		return state, fmt.Errorf("Existing bbl environment was created with a newer version of bbl. Please upgrade to bbl v%s.\n", state.BBLVersion)
	}

	return state, nil
}

// Get the earliest bbl version compatible with the given bbl state version.
func (b StateBootstrap) getBBLVersion(stateSchema int) string {
	stateToBBLVersion := map[int]string{
		3:  "3.0.0",
		5:  "4.0.0",
		6:  "4.0.0",
		7:  "4.0.0",
		8:  "4.0.0",
		9:  "4.4.0",
		10: "4.6.0",
		11: "5.1.0",
		12: "5.1.0",
		13: "5.4.0",
		14: "6.0.0",
	}
	bblVersion, ok := stateToBBLVersion[stateSchema]
	if ok {
		return bblVersion
	}
	return "dev"
}
<|endoftext|>


<commit_before>package main

import (
	"../nsq"
	"../util"
	"../util/notify"
	"log"
)

type Topic struct {
	name                 string
	newChannelChan       chan util.ChanReq
	channelMap           map[string]*Channel
	backend              nsq.BackendQueue
	incomingMessageChan  chan *nsq.Message
	msgChan              chan *nsq.Message
	routerSyncChan       chan int
	readSyncChan         chan int
	exitChan             chan int
	channelWriterStarted bool
}

var TopicMap = make(map[string]*Topic)
var newTopicChan = make(chan util.ChanReq)

// Topic constructor
func NewTopic(topicName string, inMemSize int, dataPath string) *Topic {
	topic := &Topic{name: topicName,
		newChannelChan:       make(chan util.ChanReq),
		channelMap:           make(map[string]*Channel),
		backend:              nsq.NewDiskQueue(topicName, dataPath),
		incomingMessageChan:  make(chan *nsq.Message, 5),
		msgChan:              make(chan *nsq.Message, inMemSize),
		routerSyncChan:       make(chan int, 1),
		readSyncChan:         make(chan int),
		exitChan:             make(chan int),
		channelWriterStarted: false}
	go topic.Router(inMemSize, dataPath)
	notify.Post("new_topic", topic)
	return topic
}

// GetTopic performs a thread safe operation
// to return a pointer to a Topic object (potentially new)
// see: topicFactory()
func GetTopic(topicName string) *Topic {
	topicChan := make(chan interface{})
	newTopicChan <- util.ChanReq{topicName, topicChan}
	return (<-topicChan).(*Topic)
}

// topicFactory is executed in a goroutine and manages
// the creation/retrieval of Topic objects
func TopicFactory(inMemSize int, dataPath string) {
	var topic *Topic
	var ok bool

	for {
		topicReq := <-newTopicChan
		name := topicReq.Variable.(string)
		if topic, ok = TopicMap[name]; !ok {
			topic = NewTopic(name, inMemSize, dataPath)
			TopicMap[name] = topic
			log.Printf("TOPIC(%s): created", topic.name)
		}
		topicReq.RetChan <- topic
	}
}

// GetChannel performs a thread safe operation
// to return a pointer to a Channel object (potentially new)
// for the given Topic
// see: Topic.Router()
func (t *Topic) GetChannel(channelName string) *Channel {
	channelChan := make(chan interface{})
	t.newChannelChan <- util.ChanReq{channelName, channelChan}
	return (<-channelChan).(*Channel)
}

// PutMessage writes to the appropriate incoming
// message channel
func (t *Topic) PutMessage(msg *nsq.Message) {
	// log.Printf("TOPIC(%s): PutMessage(%s, %s)", t.name, util.UuidToStr(msg.Uuid), string(msg.Body))
	t.incomingMessageChan <- msg
}

// MessagePump selects over the in-memory and backend queue and
// writes messages to every channel for this topic, synchronizing
// with the channel router
func (t *Topic) MessagePump() {
	var msg *nsq.Message

	for {
		select {
		case msg = <-t.msgChan:
		case <-t.backend.ReadReadyChan():
			buf, err := t.backend.Get()
			if err != nil {
				log.Printf("ERROR: t.backend.Get() - %s", err.Error())
				continue
			}
			msg, err = nsq.DecodeMessage(buf)
			if err != nil {
				log.Printf("ERROR: failed to decode message - %s", err.Error())
				continue
			}
		}

		t.readSyncChan <- 1
		log.Printf("TOPIC(%s): channelMap %#v", t.name, t.channelMap)
		for _, channel := range t.channelMap {
			go func(c *Channel, m *nsq.Message) {
				// log.Printf("TOPIC(%s): writing message to channel(%s)", t.name, c.name)
				c.PutMessage(m)
			}(channel, msg)
		}
		t.routerSyncChan <- 1
	}
}

// Router handles muxing of Topic messages including
// creation of new Channel objects, proxying messages
// to memory or backend, and synchronizing reads
func (t *Topic) Router(inMemSize int, dataPath string) {
	var msg *nsq.Message

	for {
		select {
		case channelReq := <-t.newChannelChan:
			name := channelReq.Variable.(string)
			channel, ok := t.channelMap[name]
			if !ok {
				channel = NewChannel(name, inMemSize, dataPath)
				t.channelMap[name] = channel
				log.Printf("TOPIC(%s): new channel(%s)", t.name, channel.name)
			}
			channelReq.RetChan <- channel
			if !t.channelWriterStarted {
				go t.MessagePump()
				t.channelWriterStarted = true
			}
		case msg = <-t.incomingMessageChan:
			select {
			case t.msgChan <- msg:
				// log.Printf("TOPIC(%s): wrote to messageChan", t.name)
			default:
				data, err := msg.Encode()
				if err != nil {
					log.Printf("ERROR: failed to Encode() message - %s", err.Error())
					// TODO: shrug
					continue
				}
				err = t.backend.Put(data)
				if err != nil {
					log.Printf("ERROR: t.backend.Put() - %s", err.Error())
					// TODO: requeue?
				}
				// log.Printf("TOPIC(%s): wrote to backend", t.name)
			}
		case <-t.readSyncChan:
			// log.Printf("TOPIC(%s): read sync START", t.name)
			<-t.routerSyncChan
			// log.Printf("TOPIC(%s): read sync END", t.name)
		case <-t.exitChan:
			return
		}
	}
}

func (t *Topic) Close() error {
	var err error

	log.Printf("TOPIC(%s): closing", t.name)

	t.exitChan <- 1

	for _, channel := range t.channelMap {
		err = channel.Close()
		if err != nil {
			// we need to continue regardless of error to close all the channels
			log.Printf("ERROR: channel(%s) close - %s", channel.name, err.Error())
		}
	}

	err = t.backend.Close()
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>use atomic.CompareAndSwap for determining if we need to start a topic's message pump<commit_after>package main

import (
	"../nsq"
	"../util"
	"../util/notify"
	"log"
	"sync/atomic"
)

type Topic struct {
	name                 string
	newChannelChan       chan util.ChanReq
	channelMap           map[string]*Channel
	backend              nsq.BackendQueue
	incomingMessageChan  chan *nsq.Message
	msgChan              chan *nsq.Message
	routerSyncChan       chan int
	readSyncChan         chan int
	exitChan             chan int
	channelWriterStarted int32
}

var TopicMap = make(map[string]*Topic)
var newTopicChan = make(chan util.ChanReq)
var topicFactoryStarted = int32(0)

// Topic constructor
func NewTopic(topicName string, inMemSize int, dataPath string) *Topic {
	topic := &Topic{name: topicName,
		newChannelChan:       make(chan util.ChanReq),
		channelMap:           make(map[string]*Channel),
		backend:              nsq.NewDiskQueue(topicName, dataPath),
		incomingMessageChan:  make(chan *nsq.Message, 5),
		msgChan:              make(chan *nsq.Message, inMemSize),
		routerSyncChan:       make(chan int, 1),
		readSyncChan:         make(chan int),
		exitChan:             make(chan int),
		channelWriterStarted: 0}
	go topic.Router(inMemSize, dataPath)
	notify.Post("new_topic", topic)
	return topic
}

// GetTopic performs a thread safe operation
// to return a pointer to a Topic object (potentially new)
// see: topicFactory()
func GetTopic(topicName string) *Topic {
	topicChan := make(chan interface{})
	newTopicChan <- util.ChanReq{topicName, topicChan}
	return (<-topicChan).(*Topic)
}

// topicFactory is executed in a goroutine and manages
// the creation/retrieval of Topic objects
func TopicFactory(inMemSize int, dataPath string) {
	var topic *Topic

	if !atomic.CompareAndSwapInt32(&topicFactoryStarted, 0, 1) {
		return
	}

	for {
		topicReq, ok := <-newTopicChan
		if !ok {
			break
		}
		name := topicReq.Variable.(string)
		if topic, ok = TopicMap[name]; !ok {
			topic = NewTopic(name, inMemSize, dataPath)
			TopicMap[name] = topic
			log.Printf("TOPIC(%s): created", topic.name)
		}
		topicReq.RetChan <- topic
	}
}

// GetChannel performs a thread safe operation
// to return a pointer to a Channel object (potentially new)
// for the given Topic
// see: Topic.Router()
func (t *Topic) GetChannel(channelName string) *Channel {
	channelChan := make(chan interface{})
	t.newChannelChan <- util.ChanReq{channelName, channelChan}
	return (<-channelChan).(*Channel)
}

// PutMessage writes to the appropriate incoming
// message channel
func (t *Topic) PutMessage(msg *nsq.Message) {
	// log.Printf("TOPIC(%s): PutMessage(%s, %s)", t.name, util.UuidToStr(msg.Uuid), string(msg.Body))
	t.incomingMessageChan <- msg
}

// MessagePump selects over the in-memory and backend queue and
// writes messages to every channel for this topic, synchronizing
// with the channel router
func (t *Topic) MessagePump() {
	var msg *nsq.Message

	for {
		select {
		case msg = <-t.msgChan:
		case <-t.backend.ReadReadyChan():
			buf, err := t.backend.Get()
			if err != nil {
				log.Printf("ERROR: t.backend.Get() - %s", err.Error())
				continue
			}
			msg, err = nsq.DecodeMessage(buf)
			if err != nil {
				log.Printf("ERROR: failed to decode message - %s", err.Error())
				continue
			}
		}

		t.readSyncChan <- 1
		log.Printf("TOPIC(%s): channelMap %#v", t.name, t.channelMap)
		for _, channel := range t.channelMap {
			go func(c *Channel, m *nsq.Message) {
				// log.Printf("TOPIC(%s): writing message to channel(%s)", t.name, c.name)
				c.PutMessage(m)
			}(channel, msg)
		}
		t.routerSyncChan <- 1
	}
}

// Router handles muxing of Topic messages including
// creation of new Channel objects, proxying messages
// to memory or backend, and synchronizing reads
func (t *Topic) Router(inMemSize int, dataPath string) {
	var msg *nsq.Message

	for {
		select {
		case channelReq := <-t.newChannelChan:
			name := channelReq.Variable.(string)
			channel, ok := t.channelMap[name]
			if !ok {
				channel = NewChannel(name, inMemSize, dataPath)
				t.channelMap[name] = channel
				log.Printf("TOPIC(%s): new channel(%s)", t.name, channel.name)
			}
			channelReq.RetChan <- channel
			if atomic.CompareAndSwapInt32(&t.channelWriterStarted, 0, 1) {
				go t.MessagePump()
			}
		case msg = <-t.incomingMessageChan:
			select {
			case t.msgChan <- msg:
				// log.Printf("TOPIC(%s): wrote to messageChan", t.name)
			default:
				data, err := msg.Encode()
				if err != nil {
					log.Printf("ERROR: failed to Encode() message - %s", err.Error())
					// TODO: shrug
					continue
				}
				err = t.backend.Put(data)
				if err != nil {
					log.Printf("ERROR: t.backend.Put() - %s", err.Error())
					// TODO: requeue?
				}
				// log.Printf("TOPIC(%s): wrote to backend", t.name)
			}
		case <-t.readSyncChan:
			// log.Printf("TOPIC(%s): read sync START", t.name)
			<-t.routerSyncChan
			// log.Printf("TOPIC(%s): read sync END", t.name)
		case <-t.exitChan:
			return
		}
	}
}

func (t *Topic) Close() error {
	var err error

	log.Printf("TOPIC(%s): closing", t.name)

	t.exitChan <- 1

	for _, channel := range t.channelMap {
		err = channel.Close()
		if err != nil {
			// we need to continue regardless of error to close all the channels
			log.Printf("ERROR: channel(%s) close - %s", channel.name, err.Error())
		}
	}

	err = t.backend.Close()
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>//      ┌─────────┐                ┌───────────┐                     ┌────────┐
//      │ Browser │                │Chronograf │                     │Provider│
//      └─────────┘                └───────────┘                     └────────┘
//           │                           │                                │
//           ├─────── GET /auth ─────────▶                                │
//           │                           │                                │
//           │                           │                                │
//           ◀ ─ ─ ─302 to Provider  ─ ─ ┤                                │
//           │                           │                                │
//           │                           │                                │
//           ├──────────────── GET /auth w/ callback ─────────────────────▶
//           │                           │                                │
//           │                           │                                │
//           ◀─ ─ ─ ─ ─ ─ ─   302 to Chronograf Callback  ─ ─ ─ ─ ─ ─ ─ ─ ┤
//           │                           │                                │
//           │   Code and State from     │                                │
//           │        Provider           │                                │
//           ├───────────────────────────▶    Request token w/ code &     │
//           │                           │             state              │
//           │                           ├────────────────────────────────▶
//           │                           │                                │
//           │                           │          Response with         │
//           │                           │              Token             │
//           │   Set cookie, Redirect    │◀ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
//           │           to /            │                                │
//           ◀───────────────────────────┤                                │
//           │                           │                                │
//           │                           │                                │
//           │                           │                                │
//           │                           │                                │

package oauth2
<commit_msg>Improve documentation for oauth2 package<commit_after>// The oauth2 package provides http.Handlers necessary for implementing Oauth2
// authentication with multiple Providers.
//
// This is how the pieces of this package fit together:
//
//  ┌────────────────────────────────────────┐
//  │github.com/influxdata/chronograf/oauth2 │
//  ├────────────────────────────────────────┴────────────────────────────────────┐
//  │┌────────────────────┐                                                       │
//  ││   <<interface>>    │        ┌─────────────────────────┐                    │
//  ││   Authenticator    │        │        CookieMux        │                    │
//  │├────────────────────┤        ├─────────────────────────┤                    │
//  ││Authenticate()      │   Auth │+SuccessURL : string     │                    │
//  ││Token()             ◀────────│+FailureURL : string     │──────────┐         │
//  │└──────────△─────────┘        │+Now : func() time.Time  │          │         │
//  │           │                  └─────────────────────────┘          │         │
//  │           │                               │                       │         │
//  │           │                               │                       │         │
//  │           │                       Provider│                       │         │
//  │           │                           ┌───┘                       │         │
//  │┌──────────┴────────────┐              │                           ▽         │
//  ││          JWT          │              │                   ┌───────────────┐ │
//  │├───────────────────────┤              ▼                   │ <<interface>> │ │
//  ││+Secret : string       │      ┌───────────────┐           │   OAuth2Mux   │ │
//  ││+Now : func() time.Time│      │ <<interface>> │           ├───────────────┤ │
//  │└───────────────────────┘      │   Provider    │           │Login()        │ │
//  │                               ├───────────────┤           │Logout()       │ │
//  │                               │ID()           │           │Callback()     │ │
//  │                               │Scopes()       │           └───────────────┘ │
//  │                               │Secret()       │                             │
//  │                               │Authenticator()│                             │
//  │                               └───────────────┘                             │
//  │                                       △                                     │
//  │                                       │                                     │
//  │             ┌─────────────────────────┼─────────────────────────┐           │
//  │             │                         │                         │           │
//  │             │                         │                         │           │
//  │             │                         │                         │           │
//  │ ┌───────────────────────┐ ┌──────────────────────┐  ┌──────────────────────┐│
//  │ │        Github         │ │        Google        │  │        Heroku        ││
//  │ ├───────────────────────┤ ├──────────────────────┤  ├──────────────────────┤│
//  │ │+ClientID : string     │ │+ClientID : string    │  │+ClientID : string    ││
//  │ │+ClientSecret : string │ │+ClientSecret : string│  │+ClientSecret : string││
//  │ │+Orgs : []string       │ │+Domains : []string   │  └──────────────────────┘│
//  │ └───────────────────────┘ │+RedirectURL : string │                          │
//  │                           └──────────────────────┘                          │
//  └─────────────────────────────────────────────────────────────────────────────┘
//
// The design focuses on an Authenticator, a Provider, and an OAuth2Mux. Their
// responsibilities, respectively, are to decode and encode secrets received
// from a Provider, to perform Provider specific operations in order to extract
// information about a user, and to provide the handlers which persist secrets.
// To add a new provider, You need only implement the Provider interface, and
// add its endpoints to the server.Mux.
//
// The Oauth2 flow between a browser, backend, and a Provider that this package
// implements is pictured below for reference.
//
//      ┌─────────┐                ┌───────────┐                     ┌────────┐
//      │ Browser │                │Chronograf │                     │Provider│
//      └─────────┘                └───────────┘                     └────────┘
//           │                           │                                │
//           ├─────── GET /auth ─────────▶                                │
//           │                           │                                │
//           │                           │                                │
//           ◀ ─ ─ ─302 to Provider  ─ ─ ┤                                │
//           │                           │                                │
//           │                           │                                │
//           ├──────────────── GET /auth w/ callback ─────────────────────▶
//           │                           │                                │
//           │                           │                                │
//           ◀─ ─ ─ ─ ─ ─ ─   302 to Chronograf Callback  ─ ─ ─ ─ ─ ─ ─ ─ ┤
//           │                           │                                │
//           │   Code and State from     │                                │
//           │        Provider           │                                │
//           ├───────────────────────────▶    Request token w/ code &     │
//           │                           │             state              │
//           │                           ├────────────────────────────────▶
//           │                           │                                │
//           │                           │          Response with         │
//           │                           │              Token             │
//           │   Set cookie, Redirect    │◀ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
//           │           to /            │                                │
//           ◀───────────────────────────┤                                │
//           │                           │                                │
//           │                           │                                │
//           │                           │                                │
//           │                           │                                │
package oauth2
<|endoftext|>


<commit_before>// Copyright 2017, OpenCensus 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 opencensus contains Go support for OpenCensus.
package opencensus // import "go.opencensus.io"

// Version is the current release version of OpenCensus in use.
func Version() string {
	return "0.20.0"
}
<commit_msg>Bump up the version to 0.21.0 (#1088)<commit_after>// Copyright 2017, OpenCensus 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 opencensus contains Go support for OpenCensus.
package opencensus // import "go.opencensus.io"

// Version is the current release version of OpenCensus in use.
func Version() string {
	return "0.21.0"
}
<|endoftext|>


<commit_before>package gotrade

import (
	"testing"
)

func TestOrderCreation(t *testing.T) {
	var (
		amount       uint64
		value_amount uint64
	)
	amount = 1000
	value_amount = 50
	for _, buyOrSell := range []OrderType{Buy, Sell} {
		order, err := NewOrder(buyOrSell, amount, value_amount)
		if err != nil {
			t.Error("Error instantiating the Order")
		}
		if order.Type != buyOrSell {
			t.Errorf("%v != %v", order.Type, buyOrSell)
		}
		if order.Amount != amount {
			t.Errorf("%v != %v", order.Amount, amount)
		}
		if order.Value != value_amount {
			t.Errorf("%v != %v", order.Value, value_amount)
		}
	}
}
<commit_msg>Test bad init values<commit_after>package gotrade

import (
	"testing"
)

func TestOrderCreation(t *testing.T) {
	var (
		amount       uint64
		value_amount uint64
	)
	amount = 1000
	value_amount = 50
	for _, buyOrSell := range []OrderType{Buy, Sell} {
		order, err := NewOrder(buyOrSell, amount, value_amount)
		if err != nil {
			t.Error("Error instantiating the Order")
		}
		if order.Type != buyOrSell {
			t.Errorf("%v != %v", order.Type, buyOrSell)
		}
		if order.Amount != amount {
			t.Errorf("%v != %v", order.Amount, amount)
		}
		if order.Value != value_amount {
			t.Errorf("%v != %v", order.Value, value_amount)
		}
	}
}

func TestBadInitValues(t *testing.T) {
	order, err := NewOrder(OrderType(3), uint64(1000), uint64(100))
	if err == nil {
		t.Error("Order should not have been created with %v", OrderType(3))
	}
	if order != nil {
		t.Error("Should have not gotten a valid Order")
	}
}
<|endoftext|>


<commit_before>/*
(c) Copyright [2015] Hewlett Packard Enterprise Development LP

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 ov -
package ov

import (
	"github.com/HewlettPackard/oneview-golang/utils"
)

// LogicalDrive logical drive options
type LogicalDrive struct {
	Bootable  bool   `json:"bootable"`            // "bootable": true,
	RaidLevel string `json:"raidLevel,omitempty"` // "raidLevel": "RAID1"
}

// LocalStorageOptions -
type LocalStorageOptions struct { // "localStorage": {
	Controllers        []LocalStorageEmbeddedController `json:"controllers,omitempty"`        //  The list of embedded local storage controllers.
	Initialize         bool                             `json:"initialize,omitempty"`         // 				"initialize": true
	LogicalDrives      []LogicalDrive                   `json:"logicalDrives,omitempty"`      // "logicalDrives": [],
	ManageLocalStorage bool                             `json:"manageLocalStorage,omitempty"` // "manageLocalStorage": true,
	ReapplyState       string                           `json:"reapplyState,omitempty"`       //Current reapply state of SAN storage component.
	SasLogicalJBODs    []LogicalJbod                    `json:"sasLogicalJBODs,omitempty"`    // "sasLogicalJBODs": [],
}

// StoragePath storage path host-to-target paths
//Use GET /rest/storage-systems/{arrayid}/managedPorts?query="expectedNetworkUri EQ '/rest/fc-networks/{netowrk-id}'"
//to retrieve the storage targets for the associated network.
type StoragePath struct {
	ConnectionID   int           `json:"connectionId,omitempty"` // connectionId (required), The ID of the connection associated with this storage path. Use GET /rest/server-profiles/available-networks to retrieve the list of available networks.
	IsEnabled      bool          `json:"isEnabled"`              // isEnabled (required), Identifies whether the storage path is enabled.
	NetworkUri     utils.Nstring `json:"networkUri"`             //The URI of the network associated with this storage path
	Status         string        `json:"status,omitempty"`       // status (read only), The overall health status of the storage path.
	Targets        []Target      `json:"targets,omitempty"`      // only set when storageTargetType is TargetPorts
	TargetSelector string        `json:"targetSelector,omitempty"`
}

type Target struct {
	IpAddress string `json:"IpAddress,omitempty"`
	Name      string `json:"name,omitempty"`
	TcpPort   int    `json:"tcpPort,omitempty"`
}

type PropertiesSP struct {
	DataProtectionLevel           string        `json:"dataProtectionLevel,omitempty"`           //The data protection level of the volume.
	DataTransferLimit             int           `json:"dataTransferLimit,omitempty"`             //The data transfer limit of the volume in mebibytes.
	Description                   string        `json:"description,omitempty"`                   //The description of the volume.
	Folder                        string        `json:"folder,omitempty"`                        //The folder of the volume.
	IsAdaptiveOptimizationEnabled bool          `json:"isAdaptiveOptimizationEnabled,omitempty"` //Indicates whether or not the volume will use adaptive optimization.
	IsCompressed                  bool          `json:"isCompressed,omitempty"`                  //Indicates whether or not compression is enabled on the volume.
	IsDataReductionEnabled        bool          `json:"isDataReductionEnabled,omitempty"`        //Indicates whether or not data reduction, such as deduplication and compression, is enabled on the volume
	IsDeduplicated                bool          `json:"isDeduplicated,omitempty"`                //Indicates whether or not deduplication is enabled on the volume.
	IsEncrypted                   bool          `json:"isEncrypted,omitempty"`                   //Indicates whether or not encryption is enabled on the volume.
	IopsLimit                     int           `json:"iopsLimit,omitempty"`                     //The IOPS (input/output operations per second) limit of the volume.
	IsPinned                      bool          `json:"isPinned,omitempty"`                      //Indicates whether or not the volume is cache pinned.
	IsShareable                   *bool         `json:"isShareable,omitempty"`                   //Indicates whether the volume is shareable or private
	Name                          string        `json:"name,omitempty"`                          //The name of the volume.
	PerformancePolicy             string        `json:"performancePolicy,omitempty"`             //The performance policy of the volume.
	ProvisioningType              string        `json:"provisioningType,omitempty"`              //The provisioning type of the volume.
	Size                          int           `json:"size,omitempty"`                          //The size of the volume.
	SnapshotPool                  utils.Nstring `json:"snapshotPool,omitempty"`                  //A URI reference to the common provisioning group used to create snapshots
	StoragePool                   utils.Nstring `json:"storagePool,omitempty"`                   //The storage pool of the volume.
	TemplateVersion               string        `json:"templateVersion,omitempty"`               //The template version of the volume.
	VolumeSet                     utils.Nstring `json:"volumeSet,omitempty"`                     //URI of a volume set to use for the volum

}

type Volume struct {
	InitialScopeUris utils.Nstring `json:"initialScopeUris,omitempty"` //Initial scopes for the volume.
	IsPermanent      *bool         `json:"isPermanent,omitempty"`      //If true, indicates that the volume will persist when the profile using this volume is deleted.
	Properties       *PropertiesSP `json:"properties"`                 //The properties specific to a storage system family required for the creation of a storage volume.
	TemplateUri      utils.Nstring `json:"templateUri,omitempty"`      //URI of the storage volume template from which the volume will be created.

}

// VolumeAttachment volume attachment
type VolumeAttachment struct {
	AssociatedTemplateAttachmentId string        `json:"associatedTemplateAttachmentId,omitempty"` //A "key" value uniquely identifying the definition of a volume attachment in a template
	BootVolumePriority             string        `json:"bootVolumePriority,omitempty"`             //Identifies whether the volume will be used as a boot volume and with what priority
	ID                             int           `json:"id,omitempty"`                             // id, The ID of the attached storage volume.
	LUN                            string        `json:"lun,omitempty"`                            // lun, The logical unit number.
	LUNType                        string        `json:"lunType,omitempty"`                        // lunType(required), The logical unit number type: Auto or Manual.
	Permanent                      *bool         `json:"permanent,omitempty"`                      // permanent, If true, indicates that the volume will persist when the profile is deleted. If false, then the volume will be deleted when the profile is deleted.
	State                          string        `json:"state,omitempty"`                          // state(read only), current state of the attachment
	Status                         string        `json:"status,omitempty"`                         // status(read only), The current status of the attachment.
	StoragePaths                   []StoragePath `json:"storagePaths,omitempty"`                   // A list of host-to-target path associations.
	Volume                         *Volume       `json:"volume,omitempty"`                         //Contains properties describing a volume to be create
	VolumeStorageSystemURI         utils.Nstring `json:"volumeStorageSystemUri,omitempty"`         // The URI of the storage system associated with this volume attachment. Use GET /rest/server-profiles/available-storage-systems to retrieve the URI of the storage system associated with a volume.
	VolumeURI                      utils.Nstring `json:"volumeUri,omitempty"`                      // The URI of the storage volume associated with this volume attachment. Use GET /rest/server-profiles/available-storage-systems to retrieve the URIs of available storage volumes.
}

// Clone clone volume attachment for submits
type SanSystemCredential struct {
	ChapLevel        string        `json:"chapLevel"`        //The Challenge Handshake Authentication Protocol (CHAP) authentication method
	ChapName         string        `json:"chapName"`         //The Challenge Handshake Authentication Protocol (CHAP) name.
	ChapSecret       string        `json:"chapSecret"`       //The CHAP secret or password. This secret is automatically generated.
	ChapSource       string        `json:"chapSource"`       //The CHAP source is AutoGenerated or UserDefine
	MutualChapName   string        `json:"mutualChapName"`   //The Mutual Challenge Handshake Authentication Protocol
	MutualChapSecret string        `json:"mutualChapSecret"` //The Mutual-CHAP secret.
	StorageSystemUri utils.Nstring `json:"storageSystemUri"` //The iSCSI storage system uri for which CHAP authentication is used
}

// SanStorageOptions specify san storage
// No San
// 		"sanStorage": {
// 				"volumeAttachments": [],
// 				"manageSanStorage": false
// 		},
type SanStorageOptions struct { // sanStorage
	HostOSType                 string                `json:"hostOSType,omitempty"`                 // hostOSType(required),  The operating system type of the host. To retrieve the list of supported host OS types, issue a REST Get request using the /rest/storage-systems/host-types API.
	ManageSanStorage           bool                  `json:"manageSanStorage"`                     // manageSanStorage(required),  Identifies whether SAN storage is managed in this profile.
	ReapplyState               string                `json:"reapplyState,omitempty"`               //Current reapply state of SAN storage component.
	SanSystemCredentials       []SanSystemCredential `json:"sanSystemCredentials,omitempty"`       //array of SanSystemCredentialsV2
	SecretsGenerated           string                `json:"secretsGenerated,omitempty"`           // The date and time the SAN Storage CHAP secrets were generated
	VolumeAttachments          []VolumeAttachment    `json:"volumeAttachments,omitempty"`          // volumeAttachments, The list of storage volume attachments. array of Volume Attachment
	ScopeUri                   utils.Nstring         `json:"scopeUri,omitempty"`                   //The URI for the resource scope assignments.
	SerialNumber               string                `json:"serialNumber,omitempty"`               // serialNumber (searchable) A 10-byte value that is exposed to the Operating System as the server hardware's Serial Number. The value can be a virtual serial number, user defined serial number or physical serial number read from the server's ROM. It cannot be modified after the profile is created.
	SerialNumberType           string                `json:"serialNumberType,omitempty"`           // serialNumberType (searchable) Specifies the type of Serial Number and UUID to be programmed into the server ROM. The value can be 'Virtual', 'UserDefined', or 'Physical'. The serialNumberType defaults to 'Virtual' when serialNumber or uuid are not specified. It cannot be modified after the profile is created.
	ServerHardwareReapplyState string                `json:"serverHardwareReapplyState,omitempty"` //Current reapply state of the server that is associated with this server profile
	ServerHardwareTypeURI      utils.Nstring         `json:"serverHardwareTypeUri,omitempty"`      // serverHardwareTypeUri Identifies the server hardware type for which the Server Profile was designed. The serverHardwareTypeUri is determined when the profile is created and cannot be modified. Use GET /rest/server-hardware-types to retrieve the list of server hardware types.
	ServerHardwareURI          utils.Nstring         `json:"serverHardwareUri,omitempty"`          // serverHardwareUri Identifies the server hardware to which the server profile is currently assigned, if applicable. Use GET /rest/server-profiles/available-targets to retrieve the list of available servers.
	ServerProfileTemplateUri   utils.Nstring         `json:"serverProfileTemplateUri,omitempty"`   //Identifies the Server profile template the Server Profile is based on
	ServiceManager             string                `json:"serviceManager,omitempty"`             //Name of a service manager that is designated owner of the profile
	State                      string                `json:"state,omitempty"`                      // state (searchable, readonly) Current State of this Server Profile
	Status                     string                `json:"status,omitempty"`                     // status (searchable, readonly) Overall health status of this Server Profile
	TaskURI                    utils.Nstring         `json:"taskUri,omitempty"`                    // taskUri (read only) URI of the task currently executing or most recently executed on this server profile.
	TemplateCompliance         string                `json:"templateCompliance,omitempty"`         //The compliance state of the server profile with the server profile template.
	Type                       string                `json:"type,omitempty"`                       // type (read only) Identifies the resource type. This field should always be set to 'ServerProfileV4'.
	URI                        utils.Nstring         `json:"uri,omitempty"`                        // uri (searchable, readonly) URI of this Server Profile. The URI is automatically generated when the server profile is created and cannot be modified.
	UUID                       string                `json:"uuid,omitempty"`                       // uuid (searchable) A 36-byte value that is exposed to the Operating System as the server hardware's UUID. The value can be a virtual uuid, user defined uuid or physical uuid read from the server's ROM. It cannot be modified after the profile is created.
	WWNType                    string                `json:"wwnType,omitempty"`                    // wwnType (searchable) Specifies the type of WWN address to be programmed into the IO devices. The value can be 'Virtual' or 'Physical'. It cannot be modified after the profile is created.
}
<commit_msg>added storage<commit_after>/*
(c) Copyright [2015] Hewlett Packard Enterprise Development LP

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 ov -
package ov

import (
	"github.com/HewlettPackard/oneview-golang/utils"
)

// LogicalDrive logical drive options
type LogicalDrive struct {
	Bootable  bool   `json:"bootable"`            // "bootable": true,
	RaidLevel string `json:"raidLevel,omitempty"` // "raidLevel": "RAID1"
}

// LocalStorageOptions -
type LocalStorageOptions struct { // "localStorage": {
	ComplianceControl  string                           `json:"complianceControl,omitempty"`
	Controllers        []LocalStorageEmbeddedController `json:"controllers,omitempty"`        //  The list of embedded local storage controllers.
	Initialize         bool                             `json:"initialize,omitempty"`         // 				"initialize": true
	LogicalDrives      []LogicalDrive                   `json:"logicalDrives,omitempty"`      // "logicalDrives": [],
	ManageLocalStorage bool                             `json:"manageLocalStorage,omitempty"` // "manageLocalStorage": true,
	ReapplyState       string                           `json:"reapplyState,omitempty"`       //Current reapply state of SAN storage component.
	SasLogicalJBODs    []LogicalJbod                    `json:"sasLogicalJBODs,omitempty"`    // "sasLogicalJBODs": [],
}

// StoragePath storage path host-to-target paths
//Use GET /rest/storage-systems/{arrayid}/managedPorts?query="expectedNetworkUri EQ '/rest/fc-networks/{netowrk-id}'"
//to retrieve the storage targets for the associated network.
type StoragePath struct {
	ConnectionID   int           `json:"connectionId,omitempty"` // connectionId (required), The ID of the connection associated with this storage path. Use GET /rest/server-profiles/available-networks to retrieve the list of available networks.
	IsEnabled      bool          `json:"isEnabled"`              // isEnabled (required), Identifies whether the storage path is enabled.
	NetworkUri     utils.Nstring `json:"networkUri"`             //The URI of the network associated with this storage path
	Status         string        `json:"status,omitempty"`       // status (read only), The overall health status of the storage path.
	Targets        []Target      `json:"targets,omitempty"`      // only set when storageTargetType is TargetPorts
	TargetSelector string        `json:"targetSelector,omitempty"`
}

type Target struct {
	IpAddress string `json:"IpAddress,omitempty"`
	Name      string `json:"name,omitempty"`
	TcpPort   int    `json:"tcpPort,omitempty"`
}

type PropertiesSP struct {
	DataProtectionLevel           string        `json:"dataProtectionLevel,omitempty"`           //The data protection level of the volume.
	DataTransferLimit             int           `json:"dataTransferLimit,omitempty"`             //The data transfer limit of the volume in mebibytes.
	Description                   string        `json:"description,omitempty"`                   //The description of the volume.
	Folder                        string        `json:"folder,omitempty"`                        //The folder of the volume.
	IsAdaptiveOptimizationEnabled bool          `json:"isAdaptiveOptimizationEnabled,omitempty"` //Indicates whether or not the volume will use adaptive optimization.
	IsCompressed                  bool          `json:"isCompressed,omitempty"`                  //Indicates whether or not compression is enabled on the volume.
	IsDataReductionEnabled        bool          `json:"isDataReductionEnabled,omitempty"`        //Indicates whether or not data reduction, such as deduplication and compression, is enabled on the volume
	IsDeduplicated                bool          `json:"isDeduplicated,omitempty"`                //Indicates whether or not deduplication is enabled on the volume.
	IsEncrypted                   bool          `json:"isEncrypted,omitempty"`                   //Indicates whether or not encryption is enabled on the volume.
	IopsLimit                     int           `json:"iopsLimit,omitempty"`                     //The IOPS (input/output operations per second) limit of the volume.
	IsPinned                      bool          `json:"isPinned,omitempty"`                      //Indicates whether or not the volume is cache pinned.
	IsShareable                   *bool         `json:"isShareable,omitempty"`                   //Indicates whether the volume is shareable or private
	Name                          string        `json:"name,omitempty"`                          //The name of the volume.
	PerformancePolicy             string        `json:"performancePolicy,omitempty"`             //The performance policy of the volume.
	ProvisioningType              string        `json:"provisioningType,omitempty"`              //The provisioning type of the volume.
	Size                          int           `json:"size,omitempty"`                          //The size of the volume.
	SnapshotPool                  utils.Nstring `json:"snapshotPool,omitempty"`                  //A URI reference to the common provisioning group used to create snapshots
	StoragePool                   utils.Nstring `json:"storagePool,omitempty"`                   //The storage pool of the volume.
	TemplateVersion               string        `json:"templateVersion,omitempty"`               //The template version of the volume.
	VolumeSet                     utils.Nstring `json:"volumeSet,omitempty"`                     //URI of a volume set to use for the volum

}

type Volume struct {
	InitialScopeUris utils.Nstring `json:"initialScopeUris,omitempty"` //Initial scopes for the volume.
	IsPermanent      *bool         `json:"isPermanent,omitempty"`      //If true, indicates that the volume will persist when the profile using this volume is deleted.
	Properties       *PropertiesSP `json:"properties"`                 //The properties specific to a storage system family required for the creation of a storage volume.
	TemplateUri      utils.Nstring `json:"templateUri,omitempty"`      //URI of the storage volume template from which the volume will be created.

}

// VolumeAttachment volume attachment
type VolumeAttachment struct {
	AssociatedTemplateAttachmentId string        `json:"associatedTemplateAttachmentId,omitempty"` //A "key" value uniquely identifying the definition of a volume attachment in a template
	BootVolumePriority             string        `json:"bootVolumePriority,omitempty"`             //Identifies whether the volume will be used as a boot volume and with what priority
	ID                             int           `json:"id,omitempty"`                             // id, The ID of the attached storage volume.
	LUN                            string        `json:"lun,omitempty"`                            // lun, The logical unit number.
	LUNType                        string        `json:"lunType,omitempty"`                        // lunType(required), The logical unit number type: Auto or Manual.
	Permanent                      *bool         `json:"permanent,omitempty"`                      // permanent, If true, indicates that the volume will persist when the profile is deleted. If false, then the volume will be deleted when the profile is deleted.
	State                          string        `json:"state,omitempty"`                          // state(read only), current state of the attachment
	Status                         string        `json:"status,omitempty"`                         // status(read only), The current status of the attachment.
	StoragePaths                   []StoragePath `json:"storagePaths,omitempty"`                   // A list of host-to-target path associations.
	Volume                         *Volume       `json:"volume,omitempty"`                         //Contains properties describing a volume to be create
	VolumeStorageSystemURI         utils.Nstring `json:"volumeStorageSystemUri,omitempty"`         // The URI of the storage system associated with this volume attachment. Use GET /rest/server-profiles/available-storage-systems to retrieve the URI of the storage system associated with a volume.
	VolumeURI                      utils.Nstring `json:"volumeUri,omitempty"`                      // The URI of the storage volume associated with this volume attachment. Use GET /rest/server-profiles/available-storage-systems to retrieve the URIs of available storage volumes.
}

// Clone clone volume attachment for submits
type SanSystemCredential struct {
	ChapLevel        string        `json:"chapLevel"`        //The Challenge Handshake Authentication Protocol (CHAP) authentication method
	ChapName         string        `json:"chapName"`         //The Challenge Handshake Authentication Protocol (CHAP) name.
	ChapSecret       string        `json:"chapSecret"`       //The CHAP secret or password. This secret is automatically generated.
	ChapSource       string        `json:"chapSource"`       //The CHAP source is AutoGenerated or UserDefine
	MutualChapName   string        `json:"mutualChapName"`   //The Mutual Challenge Handshake Authentication Protocol
	MutualChapSecret string        `json:"mutualChapSecret"` //The Mutual-CHAP secret.
	StorageSystemUri utils.Nstring `json:"storageSystemUri"` //The iSCSI storage system uri for which CHAP authentication is used
}

// SanStorageOptions specify san storage
// No San
// 		"sanStorage": {
// 				"volumeAttachments": [],
// 				"manageSanStorage": false
// 		},
type SanStorageOptions struct { // sanStorage
	ComplianceControl          string                `json:"complianceControl,omitempty"`          // complianceControl
	HostOSType                 string                `json:"hostOSType,omitempty"`                 // hostOSType(required),  The operating system type of the host. To retrieve the list of supported host OS types, issue a REST Get request using the /rest/storage-systems/host-types API.
	ManageSanStorage           bool                  `json:"manageSanStorage"`                     // manageSanStorage(required),  Identifies whether SAN storage is managed in this profile.
	ReapplyState               string                `json:"reapplyState,omitempty"`               //Current reapply state of SAN storage component.
	SanSystemCredentials       []SanSystemCredential `json:"sanSystemCredentials,omitempty"`       //array of SanSystemCredentialsV2
	SecretsGenerated           string                `json:"secretsGenerated,omitempty"`           // The date and time the SAN Storage CHAP secrets were generated
	VolumeAttachments          []VolumeAttachment    `json:"volumeAttachments,omitempty"`          // volumeAttachments, The list of storage volume attachments. array of Volume Attachment
	ScopeUri                   utils.Nstring         `json:"scopeUri,omitempty"`                   //The URI for the resource scope assignments.
	SerialNumber               string                `json:"serialNumber,omitempty"`               // serialNumber (searchable) A 10-byte value that is exposed to the Operating System as the server hardware's Serial Number. The value can be a virtual serial number, user defined serial number or physical serial number read from the server's ROM. It cannot be modified after the profile is created.
	SerialNumberType           string                `json:"serialNumberType,omitempty"`           // serialNumberType (searchable) Specifies the type of Serial Number and UUID to be programmed into the server ROM. The value can be 'Virtual', 'UserDefined', or 'Physical'. The serialNumberType defaults to 'Virtual' when serialNumber or uuid are not specified. It cannot be modified after the profile is created.
	ServerHardwareReapplyState string                `json:"serverHardwareReapplyState,omitempty"` //Current reapply state of the server that is associated with this server profile
	ServerHardwareTypeURI      utils.Nstring         `json:"serverHardwareTypeUri,omitempty"`      // serverHardwareTypeUri Identifies the server hardware type for which the Server Profile was designed. The serverHardwareTypeUri is determined when the profile is created and cannot be modified. Use GET /rest/server-hardware-types to retrieve the list of server hardware types.
	ServerHardwareURI          utils.Nstring         `json:"serverHardwareUri,omitempty"`          // serverHardwareUri Identifies the server hardware to which the server profile is currently assigned, if applicable. Use GET /rest/server-profiles/available-targets to retrieve the list of available servers.
	ServerProfileTemplateUri   utils.Nstring         `json:"serverProfileTemplateUri,omitempty"`   //Identifies the Server profile template the Server Profile is based on
	ServiceManager             string                `json:"serviceManager,omitempty"`             //Name of a service manager that is designated owner of the profile
	State                      string                `json:"state,omitempty"`                      // state (searchable, readonly) Current State of this Server Profile
	Status                     string                `json:"status,omitempty"`                     // status (searchable, readonly) Overall health status of this Server Profile
	TaskURI                    utils.Nstring         `json:"taskUri,omitempty"`                    // taskUri (read only) URI of the task currently executing or most recently executed on this server profile.
	TemplateCompliance         string                `json:"templateCompliance,omitempty"`         //The compliance state of the server profile with the server profile template.
	Type                       string                `json:"type,omitempty"`                       // type (read only) Identifies the resource type. This field should always be set to 'ServerProfileV4'.
	URI                        utils.Nstring         `json:"uri,omitempty"`                        // uri (searchable, readonly) URI of this Server Profile. The URI is automatically generated when the server profile is created and cannot be modified.
	UUID                       string                `json:"uuid,omitempty"`                       // uuid (searchable) A 36-byte value that is exposed to the Operating System as the server hardware's UUID. The value can be a virtual uuid, user defined uuid or physical uuid read from the server's ROM. It cannot be modified after the profile is created.
	WWNType                    string                `json:"wwnType,omitempty"`                    // wwnType (searchable) Specifies the type of WWN address to be programmed into the IO devices. The value can be 'Virtual' or 'Physical'. It cannot be modified after the profile is created.
}
<|endoftext|>