//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//

// Code generated by MockGen. DO NOT EDIT.
// Source: ./cloudstack/BaremetalService.go

// Package cloudstack is a generated GoMock package.
package cloudstack

import (
	reflect "reflect"

	gomock "github.com/golang/mock/gomock"
)

// MockBaremetalServiceIface is a mock of BaremetalServiceIface interface.
type MockBaremetalServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockBaremetalServiceIfaceMockRecorder
}

// MockBaremetalServiceIfaceMockRecorder is the mock recorder for MockBaremetalServiceIface.
type MockBaremetalServiceIfaceMockRecorder struct {
	mock *MockBaremetalServiceIface
}

// NewMockBaremetalServiceIface creates a new mock instance.
func NewMockBaremetalServiceIface(ctrl *gomock.Controller) *MockBaremetalServiceIface {
	mock := &MockBaremetalServiceIface{ctrl: ctrl}
	mock.recorder = &MockBaremetalServiceIfaceMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockBaremetalServiceIface) EXPECT() *MockBaremetalServiceIfaceMockRecorder {
	return m.recorder
}

// AddBaremetalDhcp mocks base method.
func (m *MockBaremetalServiceIface) AddBaremetalDhcp(p *AddBaremetalDhcpParams) (*AddBaremetalDhcpResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AddBaremetalDhcp", p)
	ret0, _ := ret[0].(*AddBaremetalDhcpResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// AddBaremetalDhcp indicates an expected call of AddBaremetalDhcp.
func (mr *MockBaremetalServiceIfaceMockRecorder) AddBaremetalDhcp(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBaremetalDhcp", reflect.TypeOf((*MockBaremetalServiceIface)(nil).AddBaremetalDhcp), p)
}

// AddBaremetalPxeKickStartServer mocks base method.
func (m *MockBaremetalServiceIface) AddBaremetalPxeKickStartServer(p *AddBaremetalPxeKickStartServerParams) (*AddBaremetalPxeKickStartServerResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AddBaremetalPxeKickStartServer", p)
	ret0, _ := ret[0].(*AddBaremetalPxeKickStartServerResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// AddBaremetalPxeKickStartServer indicates an expected call of AddBaremetalPxeKickStartServer.
func (mr *MockBaremetalServiceIfaceMockRecorder) AddBaremetalPxeKickStartServer(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBaremetalPxeKickStartServer", reflect.TypeOf((*MockBaremetalServiceIface)(nil).AddBaremetalPxeKickStartServer), p)
}

// AddBaremetalPxePingServer mocks base method.
func (m *MockBaremetalServiceIface) AddBaremetalPxePingServer(p *AddBaremetalPxePingServerParams) (*AddBaremetalPxePingServerResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AddBaremetalPxePingServer", p)
	ret0, _ := ret[0].(*AddBaremetalPxePingServerResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// AddBaremetalPxePingServer indicates an expected call of AddBaremetalPxePingServer.
func (mr *MockBaremetalServiceIfaceMockRecorder) AddBaremetalPxePingServer(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBaremetalPxePingServer", reflect.TypeOf((*MockBaremetalServiceIface)(nil).AddBaremetalPxePingServer), p)
}

// AddBaremetalRct mocks base method.
func (m *MockBaremetalServiceIface) AddBaremetalRct(p *AddBaremetalRctParams) (*AddBaremetalRctResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AddBaremetalRct", p)
	ret0, _ := ret[0].(*AddBaremetalRctResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// AddBaremetalRct indicates an expected call of AddBaremetalRct.
func (mr *MockBaremetalServiceIfaceMockRecorder) AddBaremetalRct(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBaremetalRct", reflect.TypeOf((*MockBaremetalServiceIface)(nil).AddBaremetalRct), p)
}

// DeleteBaremetalRct mocks base method.
func (m *MockBaremetalServiceIface) DeleteBaremetalRct(p *DeleteBaremetalRctParams) (*DeleteBaremetalRctResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DeleteBaremetalRct", p)
	ret0, _ := ret[0].(*DeleteBaremetalRctResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// DeleteBaremetalRct indicates an expected call of DeleteBaremetalRct.
func (mr *MockBaremetalServiceIfaceMockRecorder) DeleteBaremetalRct(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBaremetalRct", reflect.TypeOf((*MockBaremetalServiceIface)(nil).DeleteBaremetalRct), p)
}

// ListBaremetalDhcp mocks base method.
func (m *MockBaremetalServiceIface) ListBaremetalDhcp(p *ListBaremetalDhcpParams) (*ListBaremetalDhcpResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListBaremetalDhcp", p)
	ret0, _ := ret[0].(*ListBaremetalDhcpResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListBaremetalDhcp indicates an expected call of ListBaremetalDhcp.
func (mr *MockBaremetalServiceIfaceMockRecorder) ListBaremetalDhcp(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListBaremetalDhcp", reflect.TypeOf((*MockBaremetalServiceIface)(nil).ListBaremetalDhcp), p)
}

// ListBaremetalPxeServers mocks base method.
func (m *MockBaremetalServiceIface) ListBaremetalPxeServers(p *ListBaremetalPxeServersParams) (*ListBaremetalPxeServersResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListBaremetalPxeServers", p)
	ret0, _ := ret[0].(*ListBaremetalPxeServersResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListBaremetalPxeServers indicates an expected call of ListBaremetalPxeServers.
func (mr *MockBaremetalServiceIfaceMockRecorder) ListBaremetalPxeServers(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListBaremetalPxeServers", reflect.TypeOf((*MockBaremetalServiceIface)(nil).ListBaremetalPxeServers), p)
}

// ListBaremetalRct mocks base method.
func (m *MockBaremetalServiceIface) ListBaremetalRct(p *ListBaremetalRctParams) (*ListBaremetalRctResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListBaremetalRct", p)
	ret0, _ := ret[0].(*ListBaremetalRctResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListBaremetalRct indicates an expected call of ListBaremetalRct.
func (mr *MockBaremetalServiceIfaceMockRecorder) ListBaremetalRct(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListBaremetalRct", reflect.TypeOf((*MockBaremetalServiceIface)(nil).ListBaremetalRct), p)
}

// NewAddBaremetalDhcpParams mocks base method.
func (m *MockBaremetalServiceIface) NewAddBaremetalDhcpParams(dhcpservertype, password, physicalnetworkid, url, username string) *AddBaremetalDhcpParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAddBaremetalDhcpParams", dhcpservertype, password, physicalnetworkid, url, username)
	ret0, _ := ret[0].(*AddBaremetalDhcpParams)
	return ret0
}

// NewAddBaremetalDhcpParams indicates an expected call of NewAddBaremetalDhcpParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewAddBaremetalDhcpParams(dhcpservertype, password, physicalnetworkid, url, username interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddBaremetalDhcpParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewAddBaremetalDhcpParams), dhcpservertype, password, physicalnetworkid, url, username)
}

// NewAddBaremetalPxeKickStartServerParams mocks base method.
func (m *MockBaremetalServiceIface) NewAddBaremetalPxeKickStartServerParams(password, physicalnetworkid, pxeservertype, tftpdir, url, username string) *AddBaremetalPxeKickStartServerParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAddBaremetalPxeKickStartServerParams", password, physicalnetworkid, pxeservertype, tftpdir, url, username)
	ret0, _ := ret[0].(*AddBaremetalPxeKickStartServerParams)
	return ret0
}

// NewAddBaremetalPxeKickStartServerParams indicates an expected call of NewAddBaremetalPxeKickStartServerParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewAddBaremetalPxeKickStartServerParams(password, physicalnetworkid, pxeservertype, tftpdir, url, username interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddBaremetalPxeKickStartServerParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewAddBaremetalPxeKickStartServerParams), password, physicalnetworkid, pxeservertype, tftpdir, url, username)
}

// NewAddBaremetalPxePingServerParams mocks base method.
func (m *MockBaremetalServiceIface) NewAddBaremetalPxePingServerParams(password, physicalnetworkid, pingdir, pingstorageserverip, pxeservertype, tftpdir, url, username string) *AddBaremetalPxePingServerParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAddBaremetalPxePingServerParams", password, physicalnetworkid, pingdir, pingstorageserverip, pxeservertype, tftpdir, url, username)
	ret0, _ := ret[0].(*AddBaremetalPxePingServerParams)
	return ret0
}

// NewAddBaremetalPxePingServerParams indicates an expected call of NewAddBaremetalPxePingServerParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewAddBaremetalPxePingServerParams(password, physicalnetworkid, pingdir, pingstorageserverip, pxeservertype, tftpdir, url, username interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddBaremetalPxePingServerParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewAddBaremetalPxePingServerParams), password, physicalnetworkid, pingdir, pingstorageserverip, pxeservertype, tftpdir, url, username)
}

// NewAddBaremetalRctParams mocks base method.
func (m *MockBaremetalServiceIface) NewAddBaremetalRctParams(baremetalrcturl string) *AddBaremetalRctParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAddBaremetalRctParams", baremetalrcturl)
	ret0, _ := ret[0].(*AddBaremetalRctParams)
	return ret0
}

// NewAddBaremetalRctParams indicates an expected call of NewAddBaremetalRctParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewAddBaremetalRctParams(baremetalrcturl interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddBaremetalRctParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewAddBaremetalRctParams), baremetalrcturl)
}

// NewDeleteBaremetalRctParams mocks base method.
func (m *MockBaremetalServiceIface) NewDeleteBaremetalRctParams(id string) *DeleteBaremetalRctParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewDeleteBaremetalRctParams", id)
	ret0, _ := ret[0].(*DeleteBaremetalRctParams)
	return ret0
}

// NewDeleteBaremetalRctParams indicates an expected call of NewDeleteBaremetalRctParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewDeleteBaremetalRctParams(id interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewDeleteBaremetalRctParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewDeleteBaremetalRctParams), id)
}

// NewListBaremetalDhcpParams mocks base method.
func (m *MockBaremetalServiceIface) NewListBaremetalDhcpParams(physicalnetworkid string) *ListBaremetalDhcpParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListBaremetalDhcpParams", physicalnetworkid)
	ret0, _ := ret[0].(*ListBaremetalDhcpParams)
	return ret0
}

// NewListBaremetalDhcpParams indicates an expected call of NewListBaremetalDhcpParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewListBaremetalDhcpParams(physicalnetworkid interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListBaremetalDhcpParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewListBaremetalDhcpParams), physicalnetworkid)
}

// NewListBaremetalPxeServersParams mocks base method.
func (m *MockBaremetalServiceIface) NewListBaremetalPxeServersParams(physicalnetworkid string) *ListBaremetalPxeServersParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListBaremetalPxeServersParams", physicalnetworkid)
	ret0, _ := ret[0].(*ListBaremetalPxeServersParams)
	return ret0
}

// NewListBaremetalPxeServersParams indicates an expected call of NewListBaremetalPxeServersParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewListBaremetalPxeServersParams(physicalnetworkid interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListBaremetalPxeServersParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewListBaremetalPxeServersParams), physicalnetworkid)
}

// NewListBaremetalRctParams mocks base method.
func (m *MockBaremetalServiceIface) NewListBaremetalRctParams() *ListBaremetalRctParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListBaremetalRctParams")
	ret0, _ := ret[0].(*ListBaremetalRctParams)
	return ret0
}

// NewListBaremetalRctParams indicates an expected call of NewListBaremetalRctParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewListBaremetalRctParams() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListBaremetalRctParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewListBaremetalRctParams))
}

// NewNotifyBaremetalProvisionDoneParams mocks base method.
func (m *MockBaremetalServiceIface) NewNotifyBaremetalProvisionDoneParams(mac string) *NotifyBaremetalProvisionDoneParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewNotifyBaremetalProvisionDoneParams", mac)
	ret0, _ := ret[0].(*NotifyBaremetalProvisionDoneParams)
	return ret0
}

// NewNotifyBaremetalProvisionDoneParams indicates an expected call of NewNotifyBaremetalProvisionDoneParams.
func (mr *MockBaremetalServiceIfaceMockRecorder) NewNotifyBaremetalProvisionDoneParams(mac interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewNotifyBaremetalProvisionDoneParams", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NewNotifyBaremetalProvisionDoneParams), mac)
}

// NotifyBaremetalProvisionDone mocks base method.
func (m *MockBaremetalServiceIface) NotifyBaremetalProvisionDone(p *NotifyBaremetalProvisionDoneParams) (*NotifyBaremetalProvisionDoneResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NotifyBaremetalProvisionDone", p)
	ret0, _ := ret[0].(*NotifyBaremetalProvisionDoneResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// NotifyBaremetalProvisionDone indicates an expected call of NotifyBaremetalProvisionDone.
func (mr *MockBaremetalServiceIfaceMockRecorder) NotifyBaremetalProvisionDone(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotifyBaremetalProvisionDone", reflect.TypeOf((*MockBaremetalServiceIface)(nil).NotifyBaremetalProvisionDone), p)
}
