<commit_before>package pool

import (
	"fmt"
	"net"
	"time"

	strfmt "github.com/go-openapi/strfmt"

	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"

	sl "github.com/maximilien/softlayer-go/softlayer"

	datatypes "github.com/maximilien/softlayer-go/data_types"

	slhelper "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/common/helper"
	operations "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/pool/client/vm"
	bslcstem "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/stemcell"
	util "github.com/cloudfoundry/bosh-softlayer-cpi/util"

	. "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/common"

	"github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/pool/models"
)

const SOFTLAYER_POOL_CREATOR_LOG_TAG = "SoftLayerPoolCreator"

type softLayerPoolCreator struct {
	softLayerClient       sl.Client
	softLayerVmPoolClient operations.SoftLayerPoolClient

	agentEnvServiceFactory AgentEnvServiceFactory

	agentOptions AgentOptions

	logger boshlog.Logger

	vmFinder VMFinder

	featureOptions FeatureOptions
}

func NewSoftLayerPoolCreator(vmFinder VMFinder, softLayerVmPoolClient operations.SoftLayerPoolClient, softLayerClient sl.Client, agentOptions AgentOptions, logger boshlog.Logger, featureOptions FeatureOptions) VMCreator {
	slhelper.TIMEOUT = 120 * time.Minute
	slhelper.POLLING_INTERVAL = 5 * time.Second

	return &softLayerPoolCreator{
		softLayerVmPoolClient: softLayerVmPoolClient,
		softLayerClient:       softLayerClient,
		agentOptions:          agentOptions,
		logger:                logger,
		vmFinder:              vmFinder,
		featureOptions:        featureOptions,
	}
}

func (c *softLayerPoolCreator) Create(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) {
	for _, network := range networks {
		switch network.Type {
		case "dynamic":
			if len(network.IP) == 0 {
				return c.createFromVMPool(agentID, stemcell, cloudProps, networks, env)
			} else {
				return c.createByOSReload(agentID, stemcell, cloudProps, networks, env)
			}
		case "vip":
			return nil, bosherr.Error("SoftLayer Not Support VIP netowrk")
		default:
			continue
		}
	}
	return nil, bosherr.Error("virtual guests must have exactly one dynamic network")
}

// Private methods
func (c *softLayerPoolCreator) createFromVMPool(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) {
	var err error
	virtualGuestTemplate, err := CreateVirtualGuestTemplate(stemcell, cloudProps, networks)
	filter := &models.VMFilter{
		CPU:         int32(virtualGuestTemplate.StartCpus),
		MemoryMb:    int32(virtualGuestTemplate.MaxMemory),
		PrivateVlan: int32(virtualGuestTemplate.PrimaryBackendNetworkComponent.NetworkVlan.Id),
		PublicVlan:  int32(virtualGuestTemplate.PrimaryNetworkComponent.NetworkVlan.Id),
		State:       models.StateFree,
	}
	orderVmResp, err := c.softLayerVmPoolClient.OrderVMByFilter(operations.NewOrderVMByFilterParams().WithBody(filter))
	if err != nil {
		_, ok := err.(*operations.OrderVMByFilterNotFound)
		if !ok {
			return nil, bosherr.WrapError(err, "Ordering vm from pool")
		} else {
			sl_vm, err := c.createBySoftlayer(agentID, stemcell, cloudProps, networks, env)
			if err != nil {
				return nil, bosherr.WrapError(err, "Creating vm in SoftLayer")
			}
			slPoolVm := &models.VM{
				Cid:         int32(sl_vm.ID()),
				CPU:         int32(virtualGuestTemplate.StartCpus),
				MemoryMb:    int32(virtualGuestTemplate.MaxMemory),
				IP:          strfmt.IPv4(sl_vm.GetPrimaryBackendIP()),
				Hostname:    sl_vm.GetFullyQualifiedDomainName(),
				PrivateVlan: int32(virtualGuestTemplate.PrimaryBackendNetworkComponent.NetworkVlan.Id),
				PublicVlan:  int32(virtualGuestTemplate.PrimaryNetworkComponent.NetworkVlan.Id),
				State:       models.StateUsing,
			}
			_, err = c.softLayerVmPoolClient.AddVM(operations.NewAddVMParams().WithBody(slPoolVm))
			if err != nil {
				return nil, bosherr.WrapError(err, "Adding vm into pool")
			}
			c.logger.Info(SOFTLAYER_POOL_CREATOR_LOG_TAG, fmt.Sprintf("Added vm %d to pool successfully", sl_vm.ID()))

			return sl_vm, nil
		}
	}
	var vm *models.VM
	var virtualGuestId int

	vm = orderVmResp.Payload.VM
	virtualGuestId = int((*vm).Cid)

	c.logger.Info(SOFTLAYER_POOL_CREATOR_LOG_TAG, fmt.Sprintf("OS reload on VirtualGuest %d using stemcell %d", virtualGuestId, stemcell.ID()))

	sl_vm_os, err := c.oSReloadVMInPool(virtualGuestId, agentID, stemcell, cloudProps, networks, env)
	if err != nil {
		return nil, bosherr.WrapError(err, "Os reloading vm in SoftLayer")
	}

	virtualGuest, err := slhelper.GetObjectDetailsOnVirtualGuest(c.softLayerClient, virtualGuestId)
	if err != nil {
		return nil, bosherr.WrapError(err, fmt.Sprintf("Getting virtual guest %d details from SoftLayer", virtualGuestId))
	}
	deviceName := &models.VM{
		Cid:         int32(virtualGuestId),
		CPU:         int32(virtualGuest.StartCpus),
		MemoryMb:    int32(virtualGuest.MaxMemory),
		IP:          strfmt.IPv4(virtualGuest.PrimaryBackendIpAddress),
		Hostname:    cloudProps.VmNamePrefix + cloudProps.Domain,
		PrivateVlan: int32(virtualGuest.PrimaryBackendNetworkComponent.NetworkVlan.Id),
		PublicVlan:  int32(virtualGuest.PrimaryNetworkComponent.NetworkVlan.Id),
		State:       models.StateUsing,
	}
	_, err = c.softLayerVmPoolClient.UpdateVM(operations.NewUpdateVMParams().WithBody(deviceName))
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Updating the hostname of vm %d in pool to using", virtualGuestId)
	}

	c.logger.Info(SOFTLAYER_POOL_CREATOR_LOG_TAG, fmt.Sprintf("vm %d using stemcell %d os reload completed", virtualGuestId, stemcell.ID()))

	return sl_vm_os, nil
}

func (c *softLayerPoolCreator) createBySoftlayer(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) {
	virtualGuestTemplate, err := CreateVirtualGuestTemplate(stemcell, cloudProps, networks)
	if err != nil {
		return nil, bosherr.WrapError(err, "Creating VirtualGuest template")
	}
<commit_msg>Missed a . in hostname when updating pool DB<commit_after>package pool

import (
	"fmt"
	"net"
	"time"

	strfmt "github.com/go-openapi/strfmt"

	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"

	sl "github.com/maximilien/softlayer-go/softlayer"

	datatypes "github.com/maximilien/softlayer-go/data_types"

	slhelper "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/common/helper"
	operations "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/pool/client/vm"
	bslcstem "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/stemcell"
	util "github.com/cloudfoundry/bosh-softlayer-cpi/util"

	. "github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/common"

	"github.com/cloudfoundry/bosh-softlayer-cpi/softlayer/pool/models"
)

const SOFTLAYER_POOL_CREATOR_LOG_TAG = "SoftLayerPoolCreator"

type softLayerPoolCreator struct {
	softLayerClient       sl.Client
	softLayerVmPoolClient operations.SoftLayerPoolClient

	agentEnvServiceFactory AgentEnvServiceFactory

	agentOptions AgentOptions

	logger boshlog.Logger

	vmFinder VMFinder

	featureOptions FeatureOptions
}

func NewSoftLayerPoolCreator(vmFinder VMFinder, softLayerVmPoolClient operations.SoftLayerPoolClient, softLayerClient sl.Client, agentOptions AgentOptions, logger boshlog.Logger, featureOptions FeatureOptions) VMCreator {
	slhelper.TIMEOUT = 120 * time.Minute
	slhelper.POLLING_INTERVAL = 5 * time.Second

	return &softLayerPoolCreator{
		softLayerVmPoolClient: softLayerVmPoolClient,
		softLayerClient:       softLayerClient,
		agentOptions:          agentOptions,
		logger:                logger,
		vmFinder:              vmFinder,
		featureOptions:        featureOptions,
	}
}

func (c *softLayerPoolCreator) Create(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) {
	for _, network := range networks {
		switch network.Type {
		case "dynamic":
			if len(network.IP) == 0 {
				return c.createFromVMPool(agentID, stemcell, cloudProps, networks, env)
			} else {
				return c.createByOSReload(agentID, stemcell, cloudProps, networks, env)
			}
		case "vip":
			return nil, bosherr.Error("SoftLayer Not Support VIP netowrk")
		default:
			continue
		}
	}
	return nil, bosherr.Error("virtual guests must have exactly one dynamic network")
}

// Private methods
func (c *softLayerPoolCreator) createFromVMPool(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) {
	var err error
	virtualGuestTemplate, err := CreateVirtualGuestTemplate(stemcell, cloudProps, networks)
	filter := &models.VMFilter{
		CPU:         int32(virtualGuestTemplate.StartCpus),
		MemoryMb:    int32(virtualGuestTemplate.MaxMemory),
		PrivateVlan: int32(virtualGuestTemplate.PrimaryBackendNetworkComponent.NetworkVlan.Id),
		PublicVlan:  int32(virtualGuestTemplate.PrimaryNetworkComponent.NetworkVlan.Id),
		State:       models.StateFree,
	}
	orderVmResp, err := c.softLayerVmPoolClient.OrderVMByFilter(operations.NewOrderVMByFilterParams().WithBody(filter))
	if err != nil {
		_, ok := err.(*operations.OrderVMByFilterNotFound)
		if !ok {
			return nil, bosherr.WrapError(err, "Ordering vm from pool")
		} else {
			sl_vm, err := c.createBySoftlayer(agentID, stemcell, cloudProps, networks, env)
			if err != nil {
				return nil, bosherr.WrapError(err, "Creating vm in SoftLayer")
			}
			slPoolVm := &models.VM{
				Cid:         int32(sl_vm.ID()),
				CPU:         int32(virtualGuestTemplate.StartCpus),
				MemoryMb:    int32(virtualGuestTemplate.MaxMemory),
				IP:          strfmt.IPv4(sl_vm.GetPrimaryBackendIP()),
				Hostname:    sl_vm.GetFullyQualifiedDomainName(),
				PrivateVlan: int32(virtualGuestTemplate.PrimaryBackendNetworkComponent.NetworkVlan.Id),
				PublicVlan:  int32(virtualGuestTemplate.PrimaryNetworkComponent.NetworkVlan.Id),
				State:       models.StateUsing,
			}
			_, err = c.softLayerVmPoolClient.AddVM(operations.NewAddVMParams().WithBody(slPoolVm))
			if err != nil {
				return nil, bosherr.WrapError(err, "Adding vm into pool")
			}
			c.logger.Info(SOFTLAYER_POOL_CREATOR_LOG_TAG, fmt.Sprintf("Added vm %d to pool successfully", sl_vm.ID()))

			return sl_vm, nil
		}
	}
	var vm *models.VM
	var virtualGuestId int

	vm = orderVmResp.Payload.VM
	virtualGuestId = int((*vm).Cid)

	c.logger.Info(SOFTLAYER_POOL_CREATOR_LOG_TAG, fmt.Sprintf("OS reload on VirtualGuest %d using stemcell %d", virtualGuestId, stemcell.ID()))

	sl_vm_os, err := c.oSReloadVMInPool(virtualGuestId, agentID, stemcell, cloudProps, networks, env)
	if err != nil {
		return nil, bosherr.WrapError(err, "Os reloading vm in SoftLayer")
	}

	virtualGuest, err := slhelper.GetObjectDetailsOnVirtualGuest(c.softLayerClient, virtualGuestId)
	if err != nil {
		return nil, bosherr.WrapError(err, fmt.Sprintf("Getting virtual guest %d details from SoftLayer", virtualGuestId))
	}
	deviceName := &models.VM{
		Cid:         int32(virtualGuestId),
		CPU:         int32(virtualGuest.StartCpus),
		MemoryMb:    int32(virtualGuest.MaxMemory),
		IP:          strfmt.IPv4(virtualGuest.PrimaryBackendIpAddress),
		Hostname:    cloudProps.VmNamePrefix + "." + cloudProps.Domain,
		PrivateVlan: int32(virtualGuest.PrimaryBackendNetworkComponent.NetworkVlan.Id),
		PublicVlan:  int32(virtualGuest.PrimaryNetworkComponent.NetworkVlan.Id),
		State:       models.StateUsing,
	}
	_, err = c.softLayerVmPoolClient.UpdateVM(operations.NewUpdateVMParams().WithBody(deviceName))
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Updating the hostname of vm %d in pool to using", virtualGuestId)
	}

	c.logger.Info(SOFTLAYER_POOL_CREATOR_LOG_TAG, fmt.Sprintf("vm %d using stemcell %d os reload completed", virtualGuestId, stemcell.ID()))

	return sl_vm_os, nil
}

func (c *softLayerPoolCreator) createBySoftlayer(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) {
	virtualGuestTemplate, err := CreateVirtualGuestTemplate(stemcell, cloudProps, networks)
	if err != nil {
		return nil, bosherr.WrapError(err, "Creating VirtualGuest template")
	}

{'fraction_non_alphanumeric': 0.10088899763477693, 'fraction_numerical': 0.005709159122420683, 'mean_word_length': 4.9037072701011075, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5550879', 'n_tokens_mistral': 4372, 'n_tokens_neox': 4010, 'n_words': 791}