mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CloudStack CLOUDSTACK-774
Supporting kickstart in CloudStack baremetal merge baremetal feature to master
This commit is contained in:
parent
867cb4aa81
commit
1f7eaf3d61
@ -313,4 +313,10 @@ public class EventTypes {
|
|||||||
public static final String EVENT_AUTOSCALEVMGROUP_UPDATE = "AUTOSCALEVMGROUP.UPDATE";
|
public static final String EVENT_AUTOSCALEVMGROUP_UPDATE = "AUTOSCALEVMGROUP.UPDATE";
|
||||||
public static final String EVENT_AUTOSCALEVMGROUP_ENABLE = "AUTOSCALEVMGROUP.ENABLE";
|
public static final String EVENT_AUTOSCALEVMGROUP_ENABLE = "AUTOSCALEVMGROUP.ENABLE";
|
||||||
public static final String EVENT_AUTOSCALEVMGROUP_DISABLE = "AUTOSCALEVMGROUP.DISABLE";
|
public static final String EVENT_AUTOSCALEVMGROUP_DISABLE = "AUTOSCALEVMGROUP.DISABLE";
|
||||||
|
|
||||||
|
public static final String EVENT_BAREMETAL_DHCP_SERVER_ADD = "PHYSICAL.DHCP.ADD";
|
||||||
|
public static final String EVENT_BAREMETAL_DHCP_SERVER_DELETE = "PHYSICAL.DHCP.DELETE";
|
||||||
|
|
||||||
|
public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = "PHYSICAL.PXE.ADD";
|
||||||
|
public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = "PHYSICAL.PXE.DELETE";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,8 @@ public interface Host extends StateObject<Status>, Identity, InternalIdentity {
|
|||||||
ExternalLoadBalancer(false),
|
ExternalLoadBalancer(false),
|
||||||
ExternalVirtualSwitchSupervisor(false),
|
ExternalVirtualSwitchSupervisor(false),
|
||||||
PxeServer(false),
|
PxeServer(false),
|
||||||
|
BaremetalPxe(false),
|
||||||
|
BaremetalDhcp(false),
|
||||||
TrafficMonitor(false),
|
TrafficMonitor(false),
|
||||||
|
|
||||||
ExternalDhcp(false),
|
ExternalDhcp(false),
|
||||||
|
|||||||
1
api/src/org/apache/cloudstack/api/ApiConstants.java
Normal file → Executable file
1
api/src/org/apache/cloudstack/api/ApiConstants.java
Normal file → Executable file
@ -427,6 +427,7 @@ public class ApiConstants {
|
|||||||
public static final String CONDITION_IDS = "conditionids";
|
public static final String CONDITION_IDS = "conditionids";
|
||||||
public static final String COUNTERPARAM_LIST = "counterparam";
|
public static final String COUNTERPARAM_LIST = "counterparam";
|
||||||
public static final String AUTOSCALE_USER_ID = "autoscaleuserid";
|
public static final String AUTOSCALE_USER_ID = "autoscaleuserid";
|
||||||
|
public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername";
|
||||||
|
|
||||||
public enum HostDetails {
|
public enum HostDetails {
|
||||||
all, capacity, events, stats, min;
|
all, capacity, events, stats, min;
|
||||||
|
|||||||
37
plugins/hypervisors/baremetal/pom.xml
Executable file
37
plugins/hypervisors/baremetal/pom.xml
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.cloudstack</groupId>
|
||||||
|
<artifactId>cloudstack-plugins</artifactId>
|
||||||
|
<version>4.1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>cloud-plugin-hypervisor-baremetal</artifactId>
|
||||||
|
<name>Apache CloudStack Plugin - Hypervisor Baremetal</name>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
51
plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent
Executable file
51
plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# the following is chkconfig init header
|
||||||
|
#
|
||||||
|
# cs-sgagent: cloudStack baremetal sercurity group agent
|
||||||
|
#
|
||||||
|
# chkconfig: 345 97 03
|
||||||
|
# description: This is a daemon instructed by CloudStack management server \
|
||||||
|
# to perform baremetal security group related operations\
|
||||||
|
#
|
||||||
|
# processname: cs-sgagent
|
||||||
|
# pidfile: /var/run/cssgagent.pid
|
||||||
|
#
|
||||||
|
|
||||||
|
check_status() {
|
||||||
|
pidfile='/var/run/cssgagent.pid'
|
||||||
|
if [ ! -f $pidfile ]; then
|
||||||
|
echo "cloudstack baremetal security group agent is stopped"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
pid=`cat $pidfile`
|
||||||
|
ps -p $pid > /dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "cloudstack baremetal security group agent is running, pid is $pid"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "cloudstack baremetal security group agent is stopped, but pidfile at $pidfile is not cleaned. It may be caused by the agent crashed at last time, manually cleaning it would be ok"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "usage: $0
|
||||||
|
[start|stop|restart|status]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$@" = "status" ]; then
|
||||||
|
check_status
|
||||||
|
else
|
||||||
|
python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" $@
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "$@ cloudstack baremetal security group agent .... SUCCESS"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "$@ cloudstack baremetal security group agent .... FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# Automatically generated by addcopyright.py at 01/29/2013
|
||||||
@ -0,0 +1,237 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
'''
|
||||||
|
Created on Jan 2, 2013
|
||||||
|
|
||||||
|
@author: frank
|
||||||
|
'''
|
||||||
|
import cherrypy
|
||||||
|
import sglib
|
||||||
|
import xmlobject
|
||||||
|
import types
|
||||||
|
import uuid
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
class SGRule(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.protocol = None
|
||||||
|
self.start_port = None
|
||||||
|
self.end_port = None
|
||||||
|
self.allowed_ips = []
|
||||||
|
|
||||||
|
class IPSet(object):
|
||||||
|
IPSET_TYPE = 'hash:ip'
|
||||||
|
def __init__(self, setname, ips):
|
||||||
|
self.ips = ips
|
||||||
|
self.name = setname
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
tmpname = str(uuid.uuid4()).replace('-', '')[0:30]
|
||||||
|
sglib.ShellCmd('ipset -N %s %s' % (tmpname, self.IPSET_TYPE))()
|
||||||
|
try:
|
||||||
|
for ip in self.ips:
|
||||||
|
sglib.ShellCmd('ipset -A %s %s' % (tmpname, ip))()
|
||||||
|
|
||||||
|
try:
|
||||||
|
sglib.ShellCmd('ipset -N %s %s' % (self.name, self.IPSET_TYPE))()
|
||||||
|
cherrypy.log('created new ipset: %s' % self.name)
|
||||||
|
except Exception:
|
||||||
|
cherrypy.log('%s already exists, no need to create new' % self.name)
|
||||||
|
finally:
|
||||||
|
sglib.ShellCmd('ipset -W %s %s' % (tmpname, self.name))()
|
||||||
|
sglib.ShellCmd('ipset -F %s' % tmpname)()
|
||||||
|
sglib.ShellCmd('ipset -X %s' % tmpname)()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def destroy_sets(sets_to_keep):
|
||||||
|
sets = sglib.ShellCmd('ipset list')()
|
||||||
|
for s in sets.split('\n'):
|
||||||
|
if 'Name:' in s:
|
||||||
|
set_name = s.split(':', 1)[1].strip()
|
||||||
|
if not set_name in sets_to_keep:
|
||||||
|
sglib.ShellCmd('ipset destroy %s' % set_name)()
|
||||||
|
cherrypy.log('destroyed unused ipset: %s' % set_name)
|
||||||
|
|
||||||
|
class SGAgent(object):
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _self_list(self, obj):
|
||||||
|
if isinstance(obj, types.ListType):
|
||||||
|
return obj
|
||||||
|
else:
|
||||||
|
return [obj]
|
||||||
|
|
||||||
|
def set_rules(self, req):
|
||||||
|
body = req.body
|
||||||
|
doc = xmlobject.loads(body)
|
||||||
|
vm_name = doc.vmName.text_
|
||||||
|
vm_id = doc.vmId.text_
|
||||||
|
vm_ip = doc.vmIp.text_
|
||||||
|
vm_mac = doc.vmMac.text_
|
||||||
|
sig = doc.signature.text_
|
||||||
|
seq = doc.sequenceNumber.text_
|
||||||
|
|
||||||
|
def parse_rules(rules, lst):
|
||||||
|
for i in self._self_list(rules):
|
||||||
|
r = SGRule()
|
||||||
|
r.protocol = i.protocol.text_
|
||||||
|
r.start_port = i.startPort.text_
|
||||||
|
r.end_port = i.endPort.text_
|
||||||
|
if hasattr(i, 'ip'):
|
||||||
|
for ip in self._self_list(i.ip):
|
||||||
|
r.allowed_ips.append(ip.text_)
|
||||||
|
lst.append(r)
|
||||||
|
|
||||||
|
i_rules = []
|
||||||
|
if hasattr(doc, 'ingressRules'):
|
||||||
|
parse_rules(doc.ingressRules, i_rules)
|
||||||
|
|
||||||
|
e_rules = []
|
||||||
|
if hasattr(doc, 'egressRules'):
|
||||||
|
parse_rules(doc.egressRules, e_rules)
|
||||||
|
|
||||||
|
def create_chain(name):
|
||||||
|
try:
|
||||||
|
sglib.ShellCmd('iptables -F %s' % name)()
|
||||||
|
except Exception:
|
||||||
|
sglib.ShellCmd('iptables -N %s' % name)()
|
||||||
|
|
||||||
|
def apply_rules(rules, chainname, direction, action, current_set_names):
|
||||||
|
create_chain(chainname)
|
||||||
|
for r in i_rules:
|
||||||
|
allow_any = False
|
||||||
|
if '0.0.0.0/0' in r.allowed_ips:
|
||||||
|
allow_any = True
|
||||||
|
r.allowed_ips.remove('0.0.0.0/0')
|
||||||
|
|
||||||
|
if r.allowed_ips:
|
||||||
|
setname = '_'.join([chainname, r.protocol, r.start_port, r.end_port])
|
||||||
|
ipset = IPSet(setname, r.allowed_ips)
|
||||||
|
ipset.create()
|
||||||
|
current_set_names.append(setname)
|
||||||
|
|
||||||
|
if r.protocol == 'all':
|
||||||
|
cmd = ['iptables -I', chainname, '-m state --state NEW -m set --set', setname, direction, '-j', action]
|
||||||
|
sglib.ShellCmd(' '.join(cmd))()
|
||||||
|
elif r.protocol != 'icmp':
|
||||||
|
port_range = ":".join([r.start_port, r.end_port])
|
||||||
|
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m state --state NEW -m set --set', setname, direction, '-j', action]
|
||||||
|
sglib.ShellCmd(' '.join(cmd))()
|
||||||
|
else:
|
||||||
|
port_range = "/".join([r.start_port, r.end_port])
|
||||||
|
if r.start_port == "-1":
|
||||||
|
port_range = "any"
|
||||||
|
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-m set --set', setname, direction, '-j', action]
|
||||||
|
sglib.ShellCmd(' '.join(cmd))()
|
||||||
|
|
||||||
|
|
||||||
|
if allow_any and r.protocol != 'all':
|
||||||
|
if r.protocol != 'icmp':
|
||||||
|
port_range = ":".join([r.start_port, r.end_port])
|
||||||
|
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m', 'state', '--state', 'NEW', '-j', action]
|
||||||
|
sglib.ShellCmd(' '.join(cmd))()
|
||||||
|
else:
|
||||||
|
port_range = "/".join([r.start_port, r.end_port])
|
||||||
|
if r.start_port == "-1":
|
||||||
|
port_range = "any"
|
||||||
|
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-j', action]
|
||||||
|
sglib.ShellCmd(' '.join(cmd))()
|
||||||
|
|
||||||
|
current_sets = []
|
||||||
|
i_chain_name = vm_name + '-in'
|
||||||
|
apply_rules(i_rules, i_chain_name, 'src', 'ACCEPT', current_sets)
|
||||||
|
e_chain_name = vm_name + '-eg'
|
||||||
|
apply_rules(e_rules, e_chain_name, 'dst', 'RETURN', current_sets)
|
||||||
|
|
||||||
|
if e_rules:
|
||||||
|
sglib.ShellCmd('iptables -A %s -j RETURN' % e_chain_name)
|
||||||
|
else:
|
||||||
|
sglib.ShellCmd('iptables -A %s -j DROP' % e_chain_name)
|
||||||
|
|
||||||
|
sglib.ShellCmd('iptables -A %s -j DROP' % i_chain_name)
|
||||||
|
IPSet.destroy_sets(current_sets)
|
||||||
|
|
||||||
|
|
||||||
|
def echo(self, req):
|
||||||
|
cherrypy.log("echo: I am alive")
|
||||||
|
|
||||||
|
def index(self):
|
||||||
|
req = sglib.Request.from_cherrypy_request(cherrypy.request)
|
||||||
|
cmd_name = req.headers['command']
|
||||||
|
|
||||||
|
if not hasattr(self, cmd_name):
|
||||||
|
raise ValueError("SecurityGroupAgent doesn't have a method called '%s'" % cmd_name)
|
||||||
|
method = getattr(self, cmd_name)
|
||||||
|
|
||||||
|
return method(req)
|
||||||
|
index.exposed = True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def start():
|
||||||
|
cherrypy.log.access_file = '/var/log/cs-securitygroup.log'
|
||||||
|
cherrypy.log.error_file = '/var/log/cs-securitygroup.log'
|
||||||
|
cherrypy.server.socket_host = '0.0.0.0'
|
||||||
|
cherrypy.server.socket_port = 9988
|
||||||
|
cherrypy.quickstart(SGAgent())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def stop():
|
||||||
|
cherrypy.engine.exit()
|
||||||
|
|
||||||
|
PID_FILE = '/var/run/cssgagent.pid'
|
||||||
|
class SGAgentDaemon(sglib.Daemon):
|
||||||
|
def __init__(self):
|
||||||
|
super(SGAgentDaemon, self).__init__(PID_FILE)
|
||||||
|
self.is_stopped = False
|
||||||
|
self.agent = SGAgent()
|
||||||
|
sglib.Daemon.register_atexit_hook(self._do_stop)
|
||||||
|
|
||||||
|
def _do_stop(self):
|
||||||
|
if self.is_stopped:
|
||||||
|
return
|
||||||
|
self.is_stopped = True
|
||||||
|
self.agent.stop()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.agent.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.agent.stop()
|
||||||
|
super(SGAgentDaemon, self).stop()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
usage = 'usage: python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" start|stop|restart'
|
||||||
|
if len(sys.argv) != 2 or not sys.argv[1] in ['start', 'stop', 'restart']:
|
||||||
|
print usage
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
cmd = sys.argv[1]
|
||||||
|
agentdaemon = SGAgentDaemon()
|
||||||
|
if cmd == 'start':
|
||||||
|
agentdaemon.start()
|
||||||
|
elif cmd == 'stop':
|
||||||
|
agentdaemon.stop()
|
||||||
|
else:
|
||||||
|
agentdaemon.restart()
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
@ -0,0 +1,226 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
|
||||||
|
import sys, os, time, atexit
|
||||||
|
import traceback
|
||||||
|
import subprocess
|
||||||
|
from signal import SIGTERM
|
||||||
|
import cherrypy
|
||||||
|
import copy
|
||||||
|
|
||||||
|
class Request(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.headers = None
|
||||||
|
self.body = None
|
||||||
|
self.method = None
|
||||||
|
self.query_string = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_cherrypy_request(creq):
|
||||||
|
req = Request()
|
||||||
|
req.headers = copy.copy(creq.headers)
|
||||||
|
req.body = creq.body.fp.read() if creq.body else None
|
||||||
|
req.method = copy.copy(creq.method)
|
||||||
|
req.query_string = copy.copy(creq.query_string) if creq.query_string else None
|
||||||
|
return req
|
||||||
|
|
||||||
|
class ShellError(Exception):
|
||||||
|
'''shell error'''
|
||||||
|
|
||||||
|
class ShellCmd(object):
|
||||||
|
'''
|
||||||
|
classdocs
|
||||||
|
'''
|
||||||
|
def __init__(self, cmd, workdir=None, pipe=True):
|
||||||
|
'''
|
||||||
|
Constructor
|
||||||
|
'''
|
||||||
|
self.cmd = cmd
|
||||||
|
if pipe:
|
||||||
|
self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/sh', cwd=workdir)
|
||||||
|
else:
|
||||||
|
self.process = subprocess.Popen(cmd, shell=True, executable='/bin/sh', cwd=workdir)
|
||||||
|
|
||||||
|
self.stdout = None
|
||||||
|
self.stderr = None
|
||||||
|
self.return_code = None
|
||||||
|
|
||||||
|
def __call__(self, is_exception=True):
|
||||||
|
(self.stdout, self.stderr) = self.process.communicate()
|
||||||
|
if is_exception and self.process.returncode != 0:
|
||||||
|
err = []
|
||||||
|
err.append('failed to execute shell command: %s' % self.cmd)
|
||||||
|
err.append('return code: %s' % self.process.returncode)
|
||||||
|
err.append('stdout: %s' % self.stdout)
|
||||||
|
err.append('stderr: %s' % self.stderr)
|
||||||
|
raise ShellError('\n'.join(err))
|
||||||
|
|
||||||
|
self.return_code = self.process.returncode
|
||||||
|
return self.stdout
|
||||||
|
|
||||||
|
class Daemon(object):
|
||||||
|
"""
|
||||||
|
A generic daemon class.
|
||||||
|
|
||||||
|
Usage: subclass the Daemon class and override the run() method
|
||||||
|
"""
|
||||||
|
atexit_hooks = []
|
||||||
|
|
||||||
|
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
|
||||||
|
self.stdin = stdin
|
||||||
|
self.stdout = stdout
|
||||||
|
self.stderr = stderr
|
||||||
|
self.pidfile = pidfile
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def register_atexit_hook(hook):
|
||||||
|
Daemon.atexit_hooks.append(hook)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _atexit():
|
||||||
|
for hook in Daemon.atexit_hooks:
|
||||||
|
try:
|
||||||
|
hook()
|
||||||
|
except Exception:
|
||||||
|
content = traceback.format_exc()
|
||||||
|
err = 'Exception when calling atexit hook[%s]\n%s' % (hook.__name__, content)
|
||||||
|
#logger.error(err)
|
||||||
|
|
||||||
|
def daemonize(self):
|
||||||
|
"""
|
||||||
|
do the UNIX double-fork magic, see Stevens' "Advanced
|
||||||
|
Programming in the UNIX Environment" for details (ISBN 0201563177)
|
||||||
|
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
pid = os.fork()
|
||||||
|
if pid > 0:
|
||||||
|
# exit first parent
|
||||||
|
sys.exit(0)
|
||||||
|
except OSError, e:
|
||||||
|
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# decouple from parent environment
|
||||||
|
os.chdir("/")
|
||||||
|
os.setsid()
|
||||||
|
os.umask(0)
|
||||||
|
|
||||||
|
# do second fork
|
||||||
|
try:
|
||||||
|
pid = os.fork()
|
||||||
|
if pid > 0:
|
||||||
|
# exit from second parent
|
||||||
|
sys.exit(0)
|
||||||
|
except OSError, e:
|
||||||
|
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# redirect standard file descriptors
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.stderr.flush()
|
||||||
|
si = file(self.stdin, 'r')
|
||||||
|
so = file(self.stdout, 'a+')
|
||||||
|
se = file(self.stderr, 'a+', 0)
|
||||||
|
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||||
|
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||||
|
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||||
|
|
||||||
|
# write pidfile
|
||||||
|
Daemon.register_atexit_hook(self.delpid)
|
||||||
|
atexit.register(Daemon._atexit)
|
||||||
|
pid = str(os.getpid())
|
||||||
|
file(self.pidfile,'w').write("%s\n" % pid)
|
||||||
|
|
||||||
|
def delpid(self):
|
||||||
|
os.remove(self.pidfile)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""
|
||||||
|
Start the daemon
|
||||||
|
"""
|
||||||
|
# Check for a pidfile to see if the daemon already runs
|
||||||
|
try:
|
||||||
|
pf = file(self.pidfile,'r')
|
||||||
|
pid = int(pf.read().strip())
|
||||||
|
pf.close()
|
||||||
|
except IOError:
|
||||||
|
pid = None
|
||||||
|
|
||||||
|
if pid:
|
||||||
|
pscmd = ShellCmd('ps -p %s > /dev/null' % pid)
|
||||||
|
pscmd(is_exception=False)
|
||||||
|
if pscmd.return_code == 0:
|
||||||
|
message = "Daemon already running, pid is %s\n"
|
||||||
|
sys.stderr.write(message % pid)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# Start the daemon
|
||||||
|
self.daemonize()
|
||||||
|
try:
|
||||||
|
self.run()
|
||||||
|
except Exception:
|
||||||
|
content = traceback.format_exc()
|
||||||
|
#logger.error(content)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""
|
||||||
|
Stop the daemon
|
||||||
|
"""
|
||||||
|
# Get the pid from the pidfile
|
||||||
|
try:
|
||||||
|
pf = file(self.pidfile,'r')
|
||||||
|
pid = int(pf.read().strip())
|
||||||
|
pf.close()
|
||||||
|
except IOError:
|
||||||
|
pid = None
|
||||||
|
|
||||||
|
if not pid:
|
||||||
|
message = "pidfile %s does not exist. Daemon not running?\n"
|
||||||
|
sys.stderr.write(message % self.pidfile)
|
||||||
|
return # not an error in a restart
|
||||||
|
|
||||||
|
# Try killing the daemon process
|
||||||
|
try:
|
||||||
|
while 1:
|
||||||
|
os.kill(pid, SIGTERM)
|
||||||
|
time.sleep(0.1)
|
||||||
|
except OSError, err:
|
||||||
|
err = str(err)
|
||||||
|
if err.find("No such process") > 0:
|
||||||
|
if os.path.exists(self.pidfile):
|
||||||
|
os.remove(self.pidfile)
|
||||||
|
else:
|
||||||
|
print str(err)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def restart(self):
|
||||||
|
"""
|
||||||
|
Restart the daemon
|
||||||
|
"""
|
||||||
|
self.stop()
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""
|
||||||
|
You should override this method when you subclass Daemon. It will be called after the process has been
|
||||||
|
daemonized by start() or restart().
|
||||||
|
"""
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
'''
|
||||||
|
Created on Dec 25, 2012
|
||||||
|
|
||||||
|
@author: Frank
|
||||||
|
'''
|
||||||
|
import xml.etree.ElementTree as etree
|
||||||
|
import re
|
||||||
|
import types
|
||||||
|
|
||||||
|
class XmlObject(object):
|
||||||
|
def __init__(self, tag):
|
||||||
|
self.__tag_name__ = tag
|
||||||
|
|
||||||
|
def put_attr(self, name, val):
|
||||||
|
val = val.strip().strip('\t')
|
||||||
|
setattr(self, name + '_', val)
|
||||||
|
|
||||||
|
def put_text(self, val):
|
||||||
|
val = val.strip().strip('\n').strip('\t')
|
||||||
|
if val == "":
|
||||||
|
setattr(self, 'text_', None)
|
||||||
|
else:
|
||||||
|
setattr(self, 'text_', val)
|
||||||
|
|
||||||
|
def put_node(self, name, val):
|
||||||
|
if not hasattr(self, name):
|
||||||
|
setattr(self, name, val)
|
||||||
|
return
|
||||||
|
|
||||||
|
nodes = getattr(self, name)
|
||||||
|
if not isinstance(nodes, types.ListType):
|
||||||
|
nodes = []
|
||||||
|
old = getattr(self, name)
|
||||||
|
nodes.append(old)
|
||||||
|
nodes.append(val)
|
||||||
|
setattr(self, name, nodes)
|
||||||
|
else:
|
||||||
|
nodes.append(val)
|
||||||
|
setattr(self, name, nodes)
|
||||||
|
|
||||||
|
def get(self, name, default=None):
|
||||||
|
if hasattr(self, name):
|
||||||
|
val = getattr(self, name)
|
||||||
|
if name.endswith('_'):
|
||||||
|
return val
|
||||||
|
else:
|
||||||
|
return val.text_
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name.endswith('__'):
|
||||||
|
n = name[:-1]
|
||||||
|
if hasattr(self, n):
|
||||||
|
return getattr(self, n)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
e = AttributeError('%s has no attribute %s. missing attribute %s in element <%s>' % (self.__class__.__name__, name, name, self.__tag_name__))
|
||||||
|
setattr(e, 'missing_attrib', name)
|
||||||
|
setattr(e, 'tag_name', self.__tag_name__)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
def _loads(node):
|
||||||
|
xo = XmlObject(node.tag)
|
||||||
|
for key in node.attrib.keys():
|
||||||
|
xo.put_attr(key, node.attrib.get(key))
|
||||||
|
if node.text:
|
||||||
|
xo.put_text(node.text)
|
||||||
|
for n in list(node):
|
||||||
|
sub_xo = _loads(n)
|
||||||
|
xo.put_node(n.tag, sub_xo)
|
||||||
|
return xo
|
||||||
|
|
||||||
|
def loads(xmlstr):
|
||||||
|
xmlstr = re.sub(r'xmlns=".*"', '', xmlstr)
|
||||||
|
root = etree.fromstring(xmlstr)
|
||||||
|
return _loads(root)
|
||||||
44
plugins/hypervisors/baremetal/resources/security_group_agent/setup.py
Executable file
44
plugins/hypervisors/baremetal/resources/security_group_agent/setup.py
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
version = '1.0'
|
||||||
|
|
||||||
|
setup(name='security_group_agent',
|
||||||
|
version=version,
|
||||||
|
description="security group agent for CloudStack Baremetal",
|
||||||
|
long_description="""\
|
||||||
|
security group agent for CloudStack Baremetal""",
|
||||||
|
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||||
|
keywords='security group cloudstack',
|
||||||
|
author='Frank Zhang',
|
||||||
|
author_email='frank.zhang@citrix.com',
|
||||||
|
url='http://incubator.apache.org/cloudstack/',
|
||||||
|
license='Apache License 2',
|
||||||
|
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
|
||||||
|
include_package_data=True,
|
||||||
|
zip_safe=True,
|
||||||
|
install_requires=[
|
||||||
|
'CherryPy',
|
||||||
|
],
|
||||||
|
entry_points="""
|
||||||
|
# -*- Entry points: -*-
|
||||||
|
""",
|
||||||
|
)
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
public interface BaremetalCmdbDao extends GenericDao<BaremetalCmdbVO, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
@Local(value = {BaremetalCmdbDao.class})
|
||||||
|
@DB(txn = false)
|
||||||
|
public class BaremetalCmdbDaoImpl extends GenericDaoBase<BaremetalCmdbVO, Long> implements BaremetalCmdbDao {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="baremetal_cmdb")
|
||||||
|
public class BaremetalCmdbVO {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Column(name="uuid")
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
@Column(name="zone_id")
|
||||||
|
private long zoneId;
|
||||||
|
|
||||||
|
@Column(name="url")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Column(name="password")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Column(name="username")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
public BaremetalCmdbVO() {
|
||||||
|
uuid = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getZoneId() {
|
||||||
|
return zoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZoneId(long zoneId) {
|
||||||
|
this.zoneId = zoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
public interface BaremetalDhcpDao extends GenericDao<BaremetalDhcpVO, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.Filter;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.GenericSearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
|
||||||
|
@Local(value=BaremetalDhcpDao.class)
|
||||||
|
@DB(txn=false)
|
||||||
|
public class BaremetalDhcpDaoImpl extends GenericDaoBase<BaremetalDhcpVO, Long> implements BaremetalDhcpDao {
|
||||||
|
|
||||||
|
public BaremetalDhcpDaoImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="baremetal_dhcp_devices")
|
||||||
|
public class BaremetalDhcpVO {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Column(name="uuid")
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
@Column(name = "host_id")
|
||||||
|
private long hostId;
|
||||||
|
|
||||||
|
@Column(name = "pod_id")
|
||||||
|
private long podId;
|
||||||
|
|
||||||
|
@Column(name = "physical_network_id")
|
||||||
|
private long physicalNetworkId;
|
||||||
|
|
||||||
|
@Column(name = "nsp_id")
|
||||||
|
private long networkServiceProviderId ;
|
||||||
|
|
||||||
|
@Column(name = "device_type")
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
public BaremetalDhcpVO() {
|
||||||
|
super();
|
||||||
|
this.uuid = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getHostId() {
|
||||||
|
return hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostId(long hostId) {
|
||||||
|
this.hostId = hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPhysicalNetworkId() {
|
||||||
|
return physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhysicalNetworkId(long physicalNetworkId) {
|
||||||
|
this.physicalNetworkId = physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceType() {
|
||||||
|
return deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceType(String deviceType) {
|
||||||
|
this.deviceType = deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getNetworkServiceProviderId() {
|
||||||
|
return networkServiceProviderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNetworkServiceProviderId(long networkServiceProviderId) {
|
||||||
|
this.networkServiceProviderId = networkServiceProviderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPodId() {
|
||||||
|
return podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPodId(long podId) {
|
||||||
|
this.podId = podId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
|
||||||
|
public interface BaremetalPxeDao extends GenericDao<BaremetalPxeVO, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.Filter;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.GenericSearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
|
||||||
|
@Local(value = {BaremetalPxeDao.class})
|
||||||
|
@DB(txn = false)
|
||||||
|
public class BaremetalPxeDaoImpl extends GenericDaoBase<BaremetalPxeVO, Long> implements BaremetalPxeDao {
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.database;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="baremetal_pxe_devices")
|
||||||
|
public class BaremetalPxeVO {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Column(name="uuid")
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
@Column(name = "host_id")
|
||||||
|
private long hostId;
|
||||||
|
|
||||||
|
@Column(name = "pod_id")
|
||||||
|
private long podId;
|
||||||
|
|
||||||
|
@Column(name = "physical_network_id")
|
||||||
|
private long physicalNetworkId;
|
||||||
|
|
||||||
|
@Column(name = "nsp_id")
|
||||||
|
private long networkServiceProviderId ;
|
||||||
|
|
||||||
|
@Column(name = "device_type")
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaremetalPxeVO() {
|
||||||
|
uuid = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getHostId() {
|
||||||
|
return hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostId(long hostId) {
|
||||||
|
this.hostId = hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPhysicalNetworkId() {
|
||||||
|
return physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhysicalNetworkId(long physicalNetworkId) {
|
||||||
|
this.physicalNetworkId = physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getNetworkServiceProviderId() {
|
||||||
|
return networkServiceProviderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNetworkServiceProviderId(long networkServiceProviderId) {
|
||||||
|
this.networkServiceProviderId = networkServiceProviderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPodId() {
|
||||||
|
return podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPodId(long podId) {
|
||||||
|
this.podId = podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceType() {
|
||||||
|
return deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceType(String deviceType) {
|
||||||
|
this.deviceType = deviceType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.manager;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.Parameter;
|
||||||
|
import org.apache.cloudstack.api.command.admin.host.AddHostCmd;
|
||||||
|
|
||||||
|
public class AddBaremetalHostCmd extends AddHostCmd {
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="ip address intentionally allocated to this host after provisioning")
|
||||||
|
private String vmIpAddress;
|
||||||
|
|
||||||
|
public AddBaremetalHostCmd() {
|
||||||
|
this.getFullUrlParams().put(ApiConstants.BAREMETAL_DISCOVER_NAME, BareMetalDiscoverer.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVmIpAddress() {
|
||||||
|
return vmIpAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVmIpAddress(String vmIpAddress) {
|
||||||
|
this.vmIpAddress = vmIpAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,280 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.manager;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.StartupCommand;
|
||||||
|
import com.cloud.agent.api.StartupRoutingCommand;
|
||||||
|
import com.cloud.baremetal.networkservice.BareMetalResourceBase;
|
||||||
|
import com.cloud.configuration.Config;
|
||||||
|
import com.cloud.configuration.dao.ConfigurationDao;
|
||||||
|
import com.cloud.dc.ClusterVO;
|
||||||
|
import com.cloud.dc.DataCenterVO;
|
||||||
|
import com.cloud.dc.dao.ClusterDao;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.exception.DiscoveryException;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.resource.Discoverer;
|
||||||
|
import com.cloud.resource.DiscovererBase;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.resource.ResourceStateAdapter;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
import com.cloud.resource.UnableDeleteHostException;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
import com.cloud.utils.script.Script2;
|
||||||
|
import com.cloud.utils.script.Script2.ParamType;
|
||||||
|
import com.cloud.vm.VMInstanceVO;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
|
|
||||||
|
@Local(value=Discoverer.class)
|
||||||
|
public class BareMetalDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter {
|
||||||
|
protected static final Logger s_logger = Logger.getLogger(BareMetalDiscoverer.class);
|
||||||
|
@Inject protected ClusterDao _clusterDao;
|
||||||
|
@Inject protected HostDao _hostDao;
|
||||||
|
@Inject protected DataCenterDao _dcDao;
|
||||||
|
@Inject protected VMInstanceDao _vmDao = null;
|
||||||
|
@Inject protected ResourceManager _resourceMgr;
|
||||||
|
@Inject protected ConfigurationDao _configDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
|
||||||
|
return super.configure(name, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
|
||||||
|
return super.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List<String> hostTags)
|
||||||
|
throws DiscoveryException {
|
||||||
|
|
||||||
|
String discoverName = _params.get(ApiConstants.BAREMETAL_DISCOVER_NAME);
|
||||||
|
if (!this.getClass().getName().equals(discoverName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<BareMetalResourceBase, Map<String, String>> resources = new HashMap<BareMetalResourceBase, Map<String, String>>();
|
||||||
|
Map<String, String> details = new HashMap<String, String>();
|
||||||
|
|
||||||
|
if (!url.getScheme().equals("http")) {
|
||||||
|
String msg = "urlString is not http so we're not taking care of the discovery for this: " + url;
|
||||||
|
s_logger.debug(msg);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (clusterId == null) {
|
||||||
|
String msg = "must specify cluster Id when add host";
|
||||||
|
s_logger.debug(msg);
|
||||||
|
throw new RuntimeException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (podId == null) {
|
||||||
|
String msg = "must specify pod Id when add host";
|
||||||
|
s_logger.debug(msg);
|
||||||
|
throw new RuntimeException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVO cluster = _clusterDao.findById(clusterId);
|
||||||
|
if (cluster == null || (cluster.getHypervisorType() != HypervisorType.BareMetal)) {
|
||||||
|
if (s_logger.isInfoEnabled())
|
||||||
|
s_logger.info("invalid cluster id or cluster is not for Bare Metal hosts");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataCenterVO zone = _dcDao.findById(dcId);
|
||||||
|
if (zone == null) {
|
||||||
|
throw new RuntimeException("Cannot find zone " + dcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String hostname = url.getHost();
|
||||||
|
InetAddress ia = InetAddress.getByName(hostname);
|
||||||
|
String ipmiIp = ia.getHostAddress();
|
||||||
|
String guid = UUID.nameUUIDFromBytes(ipmiIp.getBytes()).toString();
|
||||||
|
|
||||||
|
String injectScript = "scripts/util/ipmi.py";
|
||||||
|
String scriptPath = Script.findScript("", injectScript);
|
||||||
|
if (scriptPath == null) {
|
||||||
|
throw new CloudRuntimeException("Unable to find key ipmi script "
|
||||||
|
+ injectScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Script2 command = new Script2(scriptPath, s_logger);
|
||||||
|
command.add("ping");
|
||||||
|
command.add("hostname="+ipmiIp);
|
||||||
|
command.add("usrname="+username);
|
||||||
|
command.add("password="+password, ParamType.PASSWORD);
|
||||||
|
final String result = command.execute();
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", result));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVO clu = _clusterDao.findById(clusterId);
|
||||||
|
if (clu.getGuid() == null) {
|
||||||
|
clu.setGuid(UUID.randomUUID().toString());
|
||||||
|
_clusterDao.update(clusterId, clu);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
params.putAll(_params);
|
||||||
|
params.put("zone", Long.toString(dcId));
|
||||||
|
params.put("pod", Long.toString(podId));
|
||||||
|
params.put("cluster", Long.toString(clusterId));
|
||||||
|
params.put("guid", guid);
|
||||||
|
params.put(ApiConstants.PRIVATE_IP, ipmiIp);
|
||||||
|
params.put(ApiConstants.USERNAME, username);
|
||||||
|
params.put(ApiConstants.PASSWORD, password);
|
||||||
|
|
||||||
|
String resourceClassName = _configDao.getValue(Config.ExternalBaremetalResourceClassName.key());
|
||||||
|
BareMetalResourceBase resource = null;
|
||||||
|
if (resourceClassName != null) {
|
||||||
|
Class<?> clazz = Class.forName(resourceClassName);
|
||||||
|
resource = (BareMetalResourceBase) clazz.newInstance();
|
||||||
|
String externalUrl = _configDao.getValue(Config.ExternalBaremetalSystemUrl.key());
|
||||||
|
if (externalUrl == null) {
|
||||||
|
throw new IllegalArgumentException(String.format("You must specify ExternalBaremetalSystemUrl in global config page as ExternalBaremetalResourceClassName is not null"));
|
||||||
|
}
|
||||||
|
details.put(BaremetalManager.ExternalBaremetalSystemUrl, externalUrl);
|
||||||
|
} else {
|
||||||
|
resource = new BareMetalResourceBase();
|
||||||
|
}
|
||||||
|
resource.configure("Bare Metal Agent", params);
|
||||||
|
|
||||||
|
String memCapacity = (String)params.get(ApiConstants.MEMORY);
|
||||||
|
String cpuCapacity = (String)params.get(ApiConstants.CPU_SPEED);
|
||||||
|
String cpuNum = (String)params.get(ApiConstants.CPU_NUMBER);
|
||||||
|
String mac = (String)params.get(ApiConstants.HOST_MAC);
|
||||||
|
if (hostTags != null && hostTags.size() != 0) {
|
||||||
|
details.put("hostTag", hostTags.get(0));
|
||||||
|
}
|
||||||
|
details.put(ApiConstants.MEMORY, memCapacity);
|
||||||
|
details.put(ApiConstants.CPU_SPEED, cpuCapacity);
|
||||||
|
details.put(ApiConstants.CPU_NUMBER, cpuNum);
|
||||||
|
details.put(ApiConstants.HOST_MAC, mac);
|
||||||
|
details.put(ApiConstants.USERNAME, username);
|
||||||
|
details.put(ApiConstants.PASSWORD, password);
|
||||||
|
details.put(ApiConstants.PRIVATE_IP, ipmiIp);
|
||||||
|
String vmIp = (String)params.get(ApiConstants.IP_ADDRESS);
|
||||||
|
if (vmIp != null) {
|
||||||
|
details.put(ApiConstants.IP_ADDRESS, vmIp);
|
||||||
|
}
|
||||||
|
String isEchoScAgent = _configDao.getValue(Config.EnableBaremetalSecurityGroupAgentEcho.key());
|
||||||
|
details.put(BaremetalManager.EchoSecurityGroupAgent, isEchoScAgent);
|
||||||
|
|
||||||
|
resources.put(resource, details);
|
||||||
|
resource.start();
|
||||||
|
|
||||||
|
zone.setGatewayProvider(Network.Provider.ExternalGateWay.getName());
|
||||||
|
zone.setDnsProvider(Network.Provider.ExternalDhcpServer.getName());
|
||||||
|
zone.setDhcpProvider(Network.Provider.ExternalDhcpServer.getName());
|
||||||
|
_dcDao.update(zone.getId(), zone);
|
||||||
|
|
||||||
|
s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," +
|
||||||
|
"cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity));
|
||||||
|
return resources;
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.warn("Can not set up bare metal agent", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postDiscovery(List<HostVO> hosts, long msId)
|
||||||
|
throws DiscoveryException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matchHypervisor(String hypervisor) {
|
||||||
|
return hypervisor.equalsIgnoreCase(Hypervisor.HypervisorType.BareMetal.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HypervisorType getHypervisorType() {
|
||||||
|
return Hypervisor.HypervisorType.BareMetal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
|
||||||
|
List<String> hostTags) {
|
||||||
|
StartupCommand firstCmd = startup[0];
|
||||||
|
if (!(firstCmd instanceof StartupRoutingCommand)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
|
||||||
|
if (ssCmd.getHypervisorType() != HypervisorType.BareMetal) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.BareMetal, details, hostTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
|
||||||
|
if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.BareMetal) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<VMInstanceVO> deadVms = _vmDao.listByLastHostId(host.getId());
|
||||||
|
for (VMInstanceVO vm : deadVms) {
|
||||||
|
if (vm.getState() == State.Running || vm.getHostId() != null) {
|
||||||
|
throw new CloudRuntimeException("VM " + vm.getId() + "is still running on host " + host.getId());
|
||||||
|
}
|
||||||
|
_vmDao.remove(vm.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DeleteHostAnswer(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.manager;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.hypervisor.HypervisorGuru;
|
||||||
|
import com.cloud.hypervisor.HypervisorGuruBase;
|
||||||
|
import com.cloud.storage.GuestOSVO;
|
||||||
|
import com.cloud.storage.dao.GuestOSDao;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.vm.VMInstanceVO;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
|
|
||||||
|
@Local(value=HypervisorGuru.class)
|
||||||
|
public class BareMetalGuru extends HypervisorGuruBase implements HypervisorGuru {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BareMetalGuru.class);
|
||||||
|
@Inject GuestOSDao _guestOsDao;
|
||||||
|
@Inject HostDao _hostDao;
|
||||||
|
@Inject VMInstanceDao _vmDao;
|
||||||
|
|
||||||
|
protected BareMetalGuru() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HypervisorType getHypervisorType() {
|
||||||
|
return HypervisorType.BareMetal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) {
|
||||||
|
VirtualMachineTO to = toVirtualMachineTO(vm);
|
||||||
|
|
||||||
|
VMInstanceVO vo = _vmDao.findById(vm.getId());
|
||||||
|
if (vo.getLastHostId() == null) {
|
||||||
|
to.setBootArgs(BaremetalManager.DO_PXE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> details = new HashMap<String, String>();
|
||||||
|
details.put("template", vm.getTemplate().getUrl());
|
||||||
|
to.setDetails(details);
|
||||||
|
|
||||||
|
// Determine the VM's OS description
|
||||||
|
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
|
||||||
|
to.setOs(guestOS.getDisplayName());
|
||||||
|
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean trackVmHostChange() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,217 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.manager;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
|
||||||
|
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
|
||||||
|
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.configuration.Resource.ResourceType;
|
||||||
|
import com.cloud.dc.DataCenterVO;
|
||||||
|
import com.cloud.event.EventTypes;
|
||||||
|
import com.cloud.event.UsageEventVO;
|
||||||
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.storage.VMTemplateHostVO;
|
||||||
|
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||||
|
import com.cloud.storage.VMTemplateVO;
|
||||||
|
import com.cloud.storage.VMTemplateZoneVO;
|
||||||
|
import com.cloud.template.TemplateAdapter;
|
||||||
|
import com.cloud.template.TemplateAdapterBase;
|
||||||
|
import com.cloud.template.TemplateProfile;
|
||||||
|
import com.cloud.user.Account;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
@Local(value=TemplateAdapter.class)
|
||||||
|
public class BareMetalTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter {
|
||||||
|
private final static Logger s_logger = Logger.getLogger(BareMetalTemplateAdapter.class);
|
||||||
|
@Inject HostDao _hostDao;
|
||||||
|
@Inject ResourceManager _resourceMgr;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException {
|
||||||
|
TemplateProfile profile = super.prepare(cmd);
|
||||||
|
|
||||||
|
if (profile.getZoneId() == null || profile.getZoneId() == -1) {
|
||||||
|
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
|
||||||
|
for (DataCenterVO dc : dcs) {
|
||||||
|
List<HostVO> pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId());
|
||||||
|
if (pxeServers.size() == 0) {
|
||||||
|
throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + dc.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List<HostVO> pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, profile.getZoneId());
|
||||||
|
if (pxeServers.size() == 0) {
|
||||||
|
throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + profile.getZoneId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException {
|
||||||
|
throw new CloudRuntimeException("Baremetal doesn't support ISO template");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void templateCreateUsage(VMTemplateVO template, HostVO host) {
|
||||||
|
if (template.getAccountId() != Account.ACCOUNT_ID_SYSTEM) {
|
||||||
|
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), host.getDataCenterId(),
|
||||||
|
template.getId(), template.getName(), null, template.getSourceTemplateId(), 0L);
|
||||||
|
_usageEventDao.persist(usageEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VMTemplateVO create(TemplateProfile profile) {
|
||||||
|
VMTemplateVO template = persistTemplate(profile);
|
||||||
|
Long zoneId = profile.getZoneId();
|
||||||
|
|
||||||
|
/* There is no secondary storage vm for baremetal, we use pxe server id.
|
||||||
|
* Tempalte is not bound to pxeserver right now, and we assume the pxeserver
|
||||||
|
* cannot be removed once it was added. so we use host id of first found pxe
|
||||||
|
* server as reference in template_host_ref.
|
||||||
|
* This maybe a FIXME in future.
|
||||||
|
*/
|
||||||
|
VMTemplateHostVO vmTemplateHost = null;
|
||||||
|
if (zoneId == null || zoneId == -1) {
|
||||||
|
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
|
||||||
|
for (DataCenterVO dc : dcs) {
|
||||||
|
HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId()).get(0);
|
||||||
|
|
||||||
|
vmTemplateHost = _tmpltHostDao.findByHostTemplate(dc.getId(), template.getId());
|
||||||
|
if (vmTemplateHost == null) {
|
||||||
|
vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100,
|
||||||
|
Status.DOWNLOADED, null, null, null, null, template.getUrl());
|
||||||
|
_tmpltHostDao.persist(vmTemplateHost);
|
||||||
|
templateCreateUsage(template, pxe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId).get(0);
|
||||||
|
vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100,
|
||||||
|
Status.DOWNLOADED, null, null, null, null, template.getUrl());
|
||||||
|
_tmpltHostDao.persist(vmTemplateHost);
|
||||||
|
templateCreateUsage(template, pxe);
|
||||||
|
}
|
||||||
|
|
||||||
|
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateProfile prepareDelete(DeleteIsoCmd cmd) {
|
||||||
|
throw new CloudRuntimeException("Baremetal doesn't support ISO, how the delete get here???");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override @DB
|
||||||
|
public boolean delete(TemplateProfile profile) {
|
||||||
|
VMTemplateVO template = profile.getTemplate();
|
||||||
|
Long templateId = template.getId();
|
||||||
|
boolean success = true;
|
||||||
|
String zoneName;
|
||||||
|
boolean isAllZone;
|
||||||
|
|
||||||
|
if (!template.isCrossZones() && profile.getZoneId() != null) {
|
||||||
|
isAllZone = false;
|
||||||
|
zoneName = profile.getZoneId().toString();
|
||||||
|
} else {
|
||||||
|
zoneName = "all zones";
|
||||||
|
isAllZone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
|
||||||
|
Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId());
|
||||||
|
String eventType = EventTypes.EVENT_TEMPLATE_DELETE;
|
||||||
|
List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByTemplateId(templateId);
|
||||||
|
|
||||||
|
for (VMTemplateHostVO vo : templateHostVOs) {
|
||||||
|
VMTemplateHostVO lock = null;
|
||||||
|
try {
|
||||||
|
HostVO pxeServer = _hostDao.findById(vo.getHostId());
|
||||||
|
if (!isAllZone && pxeServer.getDataCenterId() != profile.getZoneId()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock = _tmpltHostDao.acquireInLockTable(vo.getId());
|
||||||
|
if (lock == null) {
|
||||||
|
s_logger.debug("Failed to acquire lock when deleting templateHostVO with ID: " + vo.getId());
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vo.setDestroyed(true);
|
||||||
|
_tmpltHostDao.update(vo.getId(), vo);
|
||||||
|
VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(pxeServer.getDataCenterId(), templateId);
|
||||||
|
if (templateZone != null) {
|
||||||
|
_tmpltZoneDao.remove(templateZone.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), pxeServer.getDataCenterId(), templateId, null);
|
||||||
|
_usageEventDao.persist(usageEvent);
|
||||||
|
} finally {
|
||||||
|
if (lock != null) {
|
||||||
|
_tmpltHostDao.releaseFromLockTable(lock.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Successfully marked template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
|
||||||
|
|
||||||
|
// If there are no more non-destroyed template host entries for this template, delete it
|
||||||
|
if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) {
|
||||||
|
long accountId = template.getAccountId();
|
||||||
|
|
||||||
|
VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (lock == null) {
|
||||||
|
s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId);
|
||||||
|
success = false;
|
||||||
|
} else if (_tmpltDao.remove(templateId)) {
|
||||||
|
// Decrement the number of templates
|
||||||
|
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (lock != null) {
|
||||||
|
_tmpltDao.releaseFromLockTable(lock.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_logger.debug("Removed template: " + template.getName() + " because all of its template host refs were marked as destroyed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.manager;
|
||||||
|
|
||||||
|
import com.cloud.network.Network.Provider;
|
||||||
|
import com.cloud.utils.component.Manager;
|
||||||
|
|
||||||
|
public interface BaremetalManager extends Manager {
|
||||||
|
public static final String EchoSecurityGroupAgent = "EchoSecurityGroupAgent";
|
||||||
|
public static final String ExternalBaremetalSystemUrl = "ExternalBaremetalSystemUrl";
|
||||||
|
public static final String DO_PXE = "doPxe";
|
||||||
|
}
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.manager;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.StopAnswer;
|
||||||
|
import com.cloud.agent.manager.Commands;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.fsm.StateListener;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachineGuru;
|
||||||
|
import com.cloud.vm.VirtualMachineManager;
|
||||||
|
import com.cloud.vm.VirtualMachineName;
|
||||||
|
import com.cloud.vm.VirtualMachine.Event;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
@Local(value = {BaremetalManager.class})
|
||||||
|
public class BaremetalManagerImpl implements BaremetalManager, StateListener<State, VirtualMachine.Event, VirtualMachine> {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalManagerImpl.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected HostDao _hostDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
VirtualMachine.State.getStateMachine().registerListener(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Baremetal Manager";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
|
||||||
|
if (newState != State.Starting && newState != State.Error && newState != State.Expunging) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vo.getHypervisorType() != HypervisorType.BareMetal) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostVO host = _hostDao.findById(vo.getHostId());
|
||||||
|
if (host == null) {
|
||||||
|
s_logger.debug("Skip oldState " + oldState + " to " + "newState " + newState + " transimtion");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_hostDao.loadDetails(host);
|
||||||
|
|
||||||
|
if (newState == State.Starting) {
|
||||||
|
host.setDetail("vmName", vo.getInstanceName());
|
||||||
|
s_logger.debug("Add vmName " + host.getDetail("vmName") + " to host " + host.getId() + " details");
|
||||||
|
} else {
|
||||||
|
if (host.getDetail("vmName") != null && host.getDetail("vmName").equalsIgnoreCase(vo.getInstanceName())) {
|
||||||
|
s_logger.debug("Remove vmName " + host.getDetail("vmName") + " from host " + host.getId() + " details");
|
||||||
|
host.getDetails().remove("vmName");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_hostDao.saveDetails(host);
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.ApiErrorCode;
|
||||||
|
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd.CommandType;
|
||||||
|
import org.apache.cloudstack.api.Parameter;
|
||||||
|
import org.apache.cloudstack.api.PlugService;
|
||||||
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.database.BaremetalDhcpVO;
|
||||||
|
import com.cloud.event.EventTypes;
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.user.UserContext;
|
||||||
|
|
||||||
|
public class AddBaremetalDhcpCmd extends BaseAsyncCmd {
|
||||||
|
private static final String s_name = "addexternaldhcpresponse";
|
||||||
|
public static final Logger s_logger = Logger.getLogger(AddBaremetalDhcpCmd.class);
|
||||||
|
|
||||||
|
@PlugService BaremetalDhcpManager mgr;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
//////////////// API parameters /////////////////////
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
|
||||||
|
private Long physicalNetworkId;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, required = true, description="Pod Id")
|
||||||
|
private Long podId;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.DHCP_SERVER_TYPE, type=CommandType.STRING, required = true, description="Type of dhcp device")
|
||||||
|
private String dhcpType;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external dhcp appliance.")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to reach external dhcp device")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach external dhcp device")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEventType() {
|
||||||
|
return EventTypes.EVENT_BAREMETAL_DHCP_SERVER_ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEventDescription() {
|
||||||
|
return "Adding an external DHCP server";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||||
|
ResourceAllocationException, NetworkRuleConflictException {
|
||||||
|
try {
|
||||||
|
BaremetalDhcpVO vo = mgr.addDchpServer(this);
|
||||||
|
BaremetalDhcpResponse response = mgr.generateApiResponse(vo);
|
||||||
|
response.setObjectName(s_name);
|
||||||
|
response.setResponseName(getCommandName());
|
||||||
|
this.setResponseObject(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.warn("Unable to add external dhcp server with url: " + getUrl(), e);
|
||||||
|
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCommandName() {
|
||||||
|
return s_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEntityOwnerId() {
|
||||||
|
return UserContext.current().getCaller().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getPodId() {
|
||||||
|
return podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPodId(Long podId) {
|
||||||
|
this.podId = podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDhcpType() {
|
||||||
|
return dhcpType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDhcpType(String dhcpType) {
|
||||||
|
this.dhcpType = dhcpType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getPhysicalNetworkId() {
|
||||||
|
return physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhysicalNetworkId(Long physicalNetworkId) {
|
||||||
|
this.physicalNetworkId = physicalNetworkId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd.CommandType;
|
||||||
|
import org.apache.cloudstack.api.Parameter;
|
||||||
|
|
||||||
|
public class AddBaremetalKickStartPxeCmd extends AddBaremetalPxeCmd {
|
||||||
|
@Parameter(name=ApiConstants.TFTP_DIR, type=CommandType.STRING, required = true, description="Tftp root directory of PXE server")
|
||||||
|
private String tftpDir;
|
||||||
|
|
||||||
|
public String getTftpDir() {
|
||||||
|
return tftpDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTftpDir(String tftpDir) {
|
||||||
|
this.tftpDir = tftpDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,144 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.ApiErrorCode;
|
||||||
|
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd.CommandType;
|
||||||
|
import org.apache.cloudstack.api.Parameter;
|
||||||
|
import org.apache.cloudstack.api.PlugService;
|
||||||
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.event.EventTypes;
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.user.UserContext;
|
||||||
|
|
||||||
|
public class AddBaremetalPxeCmd extends BaseAsyncCmd {
|
||||||
|
private static final String s_name = "addexternalpxeresponse";
|
||||||
|
public static final Logger s_logger = Logger.getLogger(AddBaremetalPxeCmd.class);
|
||||||
|
|
||||||
|
@PlugService BaremetalPxeManager pxeMgr;
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
//////////////// API parameters /////////////////////
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
|
||||||
|
private Long physicalNetworkId;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, description="Pod Id")
|
||||||
|
private Long podId;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external pxe device")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.PXE_SERVER_TYPE, type=CommandType.STRING, required = true, description="type of pxe device")
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to reach external pxe device")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach external pxe device")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEventType() {
|
||||||
|
return EventTypes.EVENT_BAREMETAL_PXE_SERVER_ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEventDescription() {
|
||||||
|
return "Adding an external pxe server";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||||
|
ResourceAllocationException, NetworkRuleConflictException {
|
||||||
|
try {
|
||||||
|
BaremetalPxeVO vo = pxeMgr.addPxeServer(this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.warn("Unable to add external pxe server with url: " + getUrl(), e);
|
||||||
|
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCommandName() {
|
||||||
|
return s_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEntityOwnerId() {
|
||||||
|
return UserContext.current().getCaller().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getPhysicalNetworkId() {
|
||||||
|
return physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhysicalNetworkId(Long physicalNetworkId) {
|
||||||
|
this.physicalNetworkId = physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getPodId() {
|
||||||
|
return podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPodId(Long podId) {
|
||||||
|
this.podId = podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceType() {
|
||||||
|
return deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceType(String deviceType) {
|
||||||
|
this.deviceType = deviceType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.Parameter;
|
||||||
|
|
||||||
|
public class AddBaremetalPxePingServerCmd extends AddBaremetalPxeCmd {
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.PING_STORAGE_SERVER_IP, type=CommandType.STRING, required = true, description="PING storage server ip")
|
||||||
|
private String pingStorageServerIp;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.PING_DIR, type=CommandType.STRING, required = true, description="Root directory on PING storage server")
|
||||||
|
private String pingDir;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.TFTP_DIR, type=CommandType.STRING, required = true, description="Tftp root directory of PXE server")
|
||||||
|
private String tftpDir;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.PING_CIFS_USERNAME, type=CommandType.STRING, description="Username of PING storage server")
|
||||||
|
private String pingStorageServerUserName;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.PING_CIFS_PASSWORD, type=CommandType.STRING, description="Password of PING storage server")
|
||||||
|
private String pingStorageServerPassword;
|
||||||
|
|
||||||
|
public String getPingStorageServerIp() {
|
||||||
|
return pingStorageServerIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPingStorageServerIp(String pingStorageServerIp) {
|
||||||
|
this.pingStorageServerIp = pingStorageServerIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPingDir() {
|
||||||
|
return pingDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPingDir(String pingDir) {
|
||||||
|
this.pingDir = pingDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTftpDir() {
|
||||||
|
return tftpDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTftpDir(String tftpDir) {
|
||||||
|
this.tftpDir = tftpDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPingStorageServerUserName() {
|
||||||
|
return pingStorageServerUserName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPingStorageServerUserName(String pingStorageServerUserName) {
|
||||||
|
this.pingStorageServerUserName = pingStorageServerUserName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPingStorageServerPassword() {
|
||||||
|
return pingStorageServerPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPingStorageServerPassword(String pingStorageServerPassword) {
|
||||||
|
this.pingStorageServerPassword = pingStorageServerPassword;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,300 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
|
||||||
|
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
|
||||||
|
import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
|
||||||
|
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
|
||||||
|
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeDao;
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
|
||||||
|
import com.cloud.dc.DataCenterVO;
|
||||||
|
import com.cloud.dc.HostPodVO;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDetailsDao;
|
||||||
|
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||||
|
import com.cloud.network.PhysicalNetworkVO;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkDao;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
import com.cloud.utils.db.SearchCriteriaService;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.NicVO;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
@Local(value=BaremetalPxeService.class)
|
||||||
|
public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BareMetalPingServiceImpl.class);
|
||||||
|
@Inject ResourceManager _resourceMgr;
|
||||||
|
@Inject PhysicalNetworkDao _physicalNetworkDao;
|
||||||
|
@Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
|
||||||
|
@Inject HostDetailsDao _hostDetailsDao;
|
||||||
|
@Inject BaremetalPxeDao _pxeDao;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile pxeNic, DeployDestination dest, ReservationContext context) {
|
||||||
|
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
|
||||||
|
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString());
|
||||||
|
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, dest.getPod().getId());
|
||||||
|
BaremetalPxeVO pxeVo = sc.find();
|
||||||
|
if (pxeVo == null) {
|
||||||
|
throw new CloudRuntimeException("No PING PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM");
|
||||||
|
}
|
||||||
|
long pxeServerId = pxeVo.getHostId();
|
||||||
|
|
||||||
|
String mac = pxeNic.getMacAddress();
|
||||||
|
String ip = pxeNic.getIp4Address();
|
||||||
|
String gateway = pxeNic.getGateway();
|
||||||
|
String mask = pxeNic.getNetmask();
|
||||||
|
String dns = pxeNic.getDns1();
|
||||||
|
if (dns == null) {
|
||||||
|
dns = pxeNic.getDns2();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String tpl = profile.getTemplate().getUrl();
|
||||||
|
assert tpl != null : "How can a null template get here!!!";
|
||||||
|
PreparePxeServerCommand cmd = new PreparePxeServerCommand(ip, mac, mask, gateway, dns, tpl,
|
||||||
|
profile.getVirtualMachine().getInstanceName(), dest.getHost().getName());
|
||||||
|
PreparePxeServerAnswer ans = (PreparePxeServerAnswer) _agentMgr.send(pxeServerId, cmd);
|
||||||
|
if (!ans.getResult()) {
|
||||||
|
s_logger.warn("Unable tot program PXE server: " + pxeVo.getId() + " because " + ans.getDetails());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
|
||||||
|
Answer anw = _agentMgr.send(dest.getHost().getId(), bootCmd);
|
||||||
|
if (!anw.getResult()) {
|
||||||
|
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + anw.getDetails());
|
||||||
|
}
|
||||||
|
|
||||||
|
return anw.getResult();
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.warn("Cannot prepare PXE server", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
|
||||||
|
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
||||||
|
if (nics.size() != 1) {
|
||||||
|
throw new CloudRuntimeException("Wrong nic number " + nics.size() + " of vm " + vm.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use last host id when VM stopped */
|
||||||
|
Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
|
||||||
|
HostVO host = _hostDao.findById(hostId);
|
||||||
|
DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
|
||||||
|
NicVO nic = nics.get(0);
|
||||||
|
String mask = nic.getNetmask();
|
||||||
|
String mac = nic.getMacAddress();
|
||||||
|
String ip = nic.getIp4Address();
|
||||||
|
String gateway = nic.getGateway();
|
||||||
|
String dns = dc.getDns1();
|
||||||
|
if (dns == null) {
|
||||||
|
dns = dc.getDns2();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
prepareCreateTemplateCommand cmd = new prepareCreateTemplateCommand(ip, mac, mask, gateway, dns, templateUrl);
|
||||||
|
Answer ans = _agentMgr.send(pxeServerId, cmd);
|
||||||
|
return ans.getResult();
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Prepare for creating baremetal template failed", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DB
|
||||||
|
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
|
||||||
|
AddBaremetalPxePingServerCmd pcmd = (AddBaremetalPxePingServerCmd)cmd;
|
||||||
|
|
||||||
|
PhysicalNetworkVO pNetwork = null;
|
||||||
|
long zoneId;
|
||||||
|
|
||||||
|
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
|
||||||
|
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
|
||||||
|
if (pNetwork == null) {
|
||||||
|
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
|
||||||
|
}
|
||||||
|
zoneId = pNetwork.getDataCenterId();
|
||||||
|
|
||||||
|
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
|
||||||
|
if (ntwkSvcProvider == null) {
|
||||||
|
throw new CloudRuntimeException("Network Service Provider: " + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName() +
|
||||||
|
" is not enabled in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
|
||||||
|
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
|
||||||
|
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
|
||||||
|
" is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
|
||||||
|
}
|
||||||
|
|
||||||
|
HostPodVO pod = _podDao.findById(cmd.getPodId());
|
||||||
|
if (pod == null) {
|
||||||
|
throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<HostVO> pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalPxe, null, cmd.getPodId(), zoneId);
|
||||||
|
if (pxes.size() != 0) {
|
||||||
|
throw new IllegalArgumentException("Already had a PXE server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
String storageServerIp = pcmd.getPingStorageServerIp();
|
||||||
|
if (storageServerIp == null) {
|
||||||
|
throw new IllegalArgumentException("No IP for storage server specified");
|
||||||
|
}
|
||||||
|
String pingDir = pcmd.getPingDir();
|
||||||
|
if (pingDir == null) {
|
||||||
|
throw new IllegalArgumentException("No direcotry for storage server specified");
|
||||||
|
}
|
||||||
|
String tftpDir = pcmd.getTftpDir();
|
||||||
|
if (tftpDir == null) {
|
||||||
|
throw new IllegalArgumentException("No TFTP directory specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
String cifsUsername = pcmd.getPingStorageServerUserName();
|
||||||
|
if (cifsUsername == null || cifsUsername.equalsIgnoreCase("")) {
|
||||||
|
cifsUsername = "xxx";
|
||||||
|
}
|
||||||
|
String cifsPassword = pcmd.getPingStorageServerPassword();
|
||||||
|
if (cifsPassword == null || cifsPassword.equalsIgnoreCase("")) {
|
||||||
|
cifsPassword = "xxx";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = new URI(cmd.getUrl());
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug(e);
|
||||||
|
throw new IllegalArgumentException(e.getMessage());
|
||||||
|
}
|
||||||
|
String ipAddress = uri.getHost();
|
||||||
|
|
||||||
|
String guid = getPxeServerGuid(Long.toString(zoneId) + "-" + pod.getId(), BaremetalPxeType.PING.toString(), ipAddress);
|
||||||
|
|
||||||
|
ServerResource resource = null;
|
||||||
|
Map params = new HashMap<String, String>();
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_POD, String.valueOf(pod.getId()));
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP, storageServerIp);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR, pingDir);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME, cifsUsername);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD, cifsPassword);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
|
||||||
|
|
||||||
|
resource = new BaremetalPingPxeResource();
|
||||||
|
try {
|
||||||
|
resource.configure("PING PXE resource", params);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug(e);
|
||||||
|
throw new CloudRuntimeException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
|
||||||
|
if (pxeServer == null) {
|
||||||
|
throw new CloudRuntimeException("Cannot add PXE server as a host");
|
||||||
|
}
|
||||||
|
|
||||||
|
BaremetalPxeVO vo = new BaremetalPxeVO();
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
vo.setHostId(pxeServer.getId());
|
||||||
|
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
|
||||||
|
vo.setPodId(pod.getId());
|
||||||
|
vo.setPhysicalNetworkId(pcmd.getPhysicalNetworkId());
|
||||||
|
vo.setDeviceType(BaremetalPxeType.PING.toString());
|
||||||
|
txn.start();
|
||||||
|
_pxeDao.persist(vo);
|
||||||
|
txn.commit();
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
|
||||||
|
BaremetalPxePingResponse response = new BaremetalPxePingResponse();
|
||||||
|
response.setId(String.valueOf(vo.getId()));
|
||||||
|
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
|
||||||
|
response.setPodId(String.valueOf(vo.getPodId()));
|
||||||
|
Map<String, String> details = _hostDetailsDao.findDetails(vo.getHostId());
|
||||||
|
response.setPingStorageServerIp(details.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP));
|
||||||
|
response.setPingDir(details.get(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR));
|
||||||
|
response.setTftpDir(details.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
|
||||||
|
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
|
||||||
|
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString());
|
||||||
|
if (cmd.getPodId() != null) {
|
||||||
|
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
|
||||||
|
if (cmd.getId() != null) {
|
||||||
|
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<BaremetalPxeVO> vos = sc.list();
|
||||||
|
List<BaremetalPxeResponse> responses = new ArrayList<BaremetalPxeResponse>(vos.size());
|
||||||
|
for (BaremetalPxeVO vo : vos) {
|
||||||
|
responses.add(getApiResponse(vo));
|
||||||
|
}
|
||||||
|
return responses;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import com.cloud.agent.AgentManager;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.vm.dao.NicDao;
|
||||||
|
|
||||||
|
public abstract class BareMetalPxeServiceBase implements BaremetalPxeService {
|
||||||
|
protected String _name;
|
||||||
|
@Inject DataCenterDao _dcDao;
|
||||||
|
@Inject HostDao _hostDao;
|
||||||
|
@Inject AgentManager _agentMgr;
|
||||||
|
@Inject HostPodDao _podDao;
|
||||||
|
@Inject NicDao _nicDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
_name = name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getPxeServerGuid(String zoneId, String name, String ip) {
|
||||||
|
return zoneId + "-" + name + "-" + ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,618 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.IAgentControl;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CheckNetworkAnswer;
|
||||||
|
import com.cloud.agent.api.CheckNetworkCommand;
|
||||||
|
import com.cloud.agent.api.CheckVirtualMachineAnswer;
|
||||||
|
import com.cloud.agent.api.CheckVirtualMachineCommand;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.MaintainAnswer;
|
||||||
|
import com.cloud.agent.api.MaintainCommand;
|
||||||
|
import com.cloud.agent.api.MigrateAnswer;
|
||||||
|
import com.cloud.agent.api.MigrateCommand;
|
||||||
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
import com.cloud.agent.api.PingRoutingCommand;
|
||||||
|
import com.cloud.agent.api.PrepareForMigrationAnswer;
|
||||||
|
import com.cloud.agent.api.PrepareForMigrationCommand;
|
||||||
|
import com.cloud.agent.api.ReadyAnswer;
|
||||||
|
import com.cloud.agent.api.ReadyCommand;
|
||||||
|
import com.cloud.agent.api.RebootAnswer;
|
||||||
|
import com.cloud.agent.api.RebootCommand;
|
||||||
|
import com.cloud.agent.api.SecurityGroupRulesCmd;
|
||||||
|
import com.cloud.agent.api.StartAnswer;
|
||||||
|
import com.cloud.agent.api.StartCommand;
|
||||||
|
import com.cloud.agent.api.StartupCommand;
|
||||||
|
import com.cloud.agent.api.StartupRoutingCommand;
|
||||||
|
import com.cloud.agent.api.StopAnswer;
|
||||||
|
import com.cloud.agent.api.StopCommand;
|
||||||
|
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
|
||||||
|
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
|
||||||
|
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
|
||||||
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
|
import com.cloud.baremetal.manager.BaremetalManager;
|
||||||
|
import com.cloud.host.Host.Type;
|
||||||
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
import com.cloud.server.ManagementServer;
|
||||||
|
import com.cloud.utils.component.ComponentLocator;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.script.OutputInterpreter;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
import com.cloud.utils.script.Script2;
|
||||||
|
import com.cloud.utils.script.Script2.ParamType;
|
||||||
|
import com.cloud.vm.VMInstanceVO;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
|
|
||||||
|
import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Local(value = ServerResource.class)
|
||||||
|
public class BareMetalResourceBase implements ServerResource {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BareMetalResourceBase.class);
|
||||||
|
protected HashMap<String, State> _vms = new HashMap<String, State>(2);
|
||||||
|
protected String _name;
|
||||||
|
protected String _uuid;
|
||||||
|
protected String _zone;
|
||||||
|
protected String _pod;
|
||||||
|
protected Long hostId;
|
||||||
|
protected String _cluster;
|
||||||
|
protected long _memCapacity;
|
||||||
|
protected long _cpuCapacity;
|
||||||
|
protected long _cpuNum;
|
||||||
|
protected String _mac;
|
||||||
|
protected String _username;
|
||||||
|
protected String _password;
|
||||||
|
protected String _ip;
|
||||||
|
protected boolean _isEchoScAgent;
|
||||||
|
protected IAgentControl _agentControl;
|
||||||
|
protected Script2 _pingCommand;
|
||||||
|
protected Script2 _setPxeBootCommand;
|
||||||
|
protected Script2 _setDiskBootCommand;
|
||||||
|
protected Script2 _rebootCommand;
|
||||||
|
protected Script2 _getStatusCommand;
|
||||||
|
protected Script2 _powerOnCommand;
|
||||||
|
protected Script2 _powerOffCommand;
|
||||||
|
protected Script2 _forcePowerOffCommand;
|
||||||
|
protected Script2 _bootOrRebootCommand;
|
||||||
|
protected String _vmName;
|
||||||
|
protected VMInstanceDao vmDao;
|
||||||
|
|
||||||
|
private void changeVmState(String vmName, VirtualMachine.State state) {
|
||||||
|
synchronized (_vms) {
|
||||||
|
_vms.put(vmName, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private State removeVmState(String vmName) {
|
||||||
|
synchronized (_vms) {
|
||||||
|
return _vms.remove(vmName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
_name = name;
|
||||||
|
_uuid = (String) params.get("guid");
|
||||||
|
try {
|
||||||
|
_memCapacity = Long.parseLong((String) params.get(ApiConstants.MEMORY)) * 1024L * 1024L;
|
||||||
|
_cpuCapacity = Long.parseLong((String) params.get(ApiConstants.CPU_SPEED));
|
||||||
|
_cpuNum = Long.parseLong((String) params.get(ApiConstants.CPU_NUMBER));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new ConfigurationException(String.format("Unable to parse number of CPU or memory capacity "
|
||||||
|
+ "or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", (String) params.get(ApiConstants.CPU_NUMBER),
|
||||||
|
(String) params.get(ApiConstants.MEMORY), (String) params.get(ApiConstants.CPU_SPEED)));
|
||||||
|
}
|
||||||
|
|
||||||
|
_zone = (String) params.get("zone");
|
||||||
|
_pod = (String) params.get("pod");
|
||||||
|
_cluster = (String) params.get("cluster");
|
||||||
|
hostId = (Long) params.get("hostId");
|
||||||
|
_ip = (String) params.get(ApiConstants.PRIVATE_IP);
|
||||||
|
_mac = (String) params.get(ApiConstants.HOST_MAC);
|
||||||
|
_username = (String) params.get(ApiConstants.USERNAME);
|
||||||
|
_password = (String) params.get(ApiConstants.PASSWORD);
|
||||||
|
_vmName = (String) params.get("vmName");
|
||||||
|
String echoScAgent = (String) params.get(BaremetalManager.EchoSecurityGroupAgent);
|
||||||
|
|
||||||
|
if (_pod == null) {
|
||||||
|
throw new ConfigurationException("Unable to get the pod");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cluster == null) {
|
||||||
|
throw new ConfigurationException("Unable to get the pod");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ip == null) {
|
||||||
|
throw new ConfigurationException("Unable to get the host address");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mac.equalsIgnoreCase("unknown")) {
|
||||||
|
throw new ConfigurationException("Unable to get the host mac address");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mac.split(":").length != 6) {
|
||||||
|
throw new ConfigurationException("Wrong MAC format(" + _mac
|
||||||
|
+ "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_uuid == null) {
|
||||||
|
throw new ConfigurationException("Unable to get the uuid");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (echoScAgent != null) {
|
||||||
|
_isEchoScAgent = Boolean.valueOf(echoScAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
String injectScript = "scripts/util/ipmi.py";
|
||||||
|
String scriptPath = Script.findScript("", injectScript);
|
||||||
|
if (scriptPath == null) {
|
||||||
|
throw new ConfigurationException("Cannot find ping script " + scriptPath);
|
||||||
|
}
|
||||||
|
_pingCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_pingCommand.add("ping");
|
||||||
|
_pingCommand.add("hostname=" + _ip);
|
||||||
|
_pingCommand.add("usrname=" + _username);
|
||||||
|
_pingCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
|
||||||
|
_setPxeBootCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_setPxeBootCommand.add("boot_dev");
|
||||||
|
_setPxeBootCommand.add("hostname=" + _ip);
|
||||||
|
_setPxeBootCommand.add("usrname=" + _username);
|
||||||
|
_setPxeBootCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
_setPxeBootCommand.add("dev=pxe");
|
||||||
|
|
||||||
|
_setDiskBootCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_setDiskBootCommand.add("boot_dev");
|
||||||
|
_setDiskBootCommand.add("hostname=" + _ip);
|
||||||
|
_setDiskBootCommand.add("usrname=" + _username);
|
||||||
|
_setDiskBootCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
_setDiskBootCommand.add("dev=disk");
|
||||||
|
|
||||||
|
_rebootCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_rebootCommand.add("reboot");
|
||||||
|
_rebootCommand.add("hostname=" + _ip);
|
||||||
|
_rebootCommand.add("usrname=" + _username);
|
||||||
|
_rebootCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
|
||||||
|
_getStatusCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_getStatusCommand.add("ping");
|
||||||
|
_getStatusCommand.add("hostname=" + _ip);
|
||||||
|
_getStatusCommand.add("usrname=" + _username);
|
||||||
|
_getStatusCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
|
||||||
|
_powerOnCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_powerOnCommand.add("power");
|
||||||
|
_powerOnCommand.add("hostname=" + _ip);
|
||||||
|
_powerOnCommand.add("usrname=" + _username);
|
||||||
|
_powerOnCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
_powerOnCommand.add("action=on");
|
||||||
|
|
||||||
|
_powerOffCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_powerOffCommand.add("power");
|
||||||
|
_powerOffCommand.add("hostname=" + _ip);
|
||||||
|
_powerOffCommand.add("usrname=" + _username);
|
||||||
|
_powerOffCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
_powerOffCommand.add("action=soft");
|
||||||
|
|
||||||
|
_forcePowerOffCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_forcePowerOffCommand.add("power");
|
||||||
|
_forcePowerOffCommand.add("hostname=" + _ip);
|
||||||
|
_forcePowerOffCommand.add("usrname=" + _username);
|
||||||
|
_forcePowerOffCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
_forcePowerOffCommand.add("action=off");
|
||||||
|
|
||||||
|
_bootOrRebootCommand = new Script2(scriptPath, s_logger);
|
||||||
|
_bootOrRebootCommand.add("boot_or_reboot");
|
||||||
|
_bootOrRebootCommand.add("hostname=" + _ip);
|
||||||
|
_bootOrRebootCommand.add("usrname=" + _username);
|
||||||
|
_bootOrRebootCommand.add("password=" + _password, ParamType.PASSWORD);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean doScript(Script cmd) {
|
||||||
|
return doScript(cmd, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean doScript(Script cmd, OutputInterpreter interpreter) {
|
||||||
|
int retry = 5;
|
||||||
|
String res = null;
|
||||||
|
while (retry-- > 0) {
|
||||||
|
if (interpreter == null) {
|
||||||
|
res = cmd.execute();
|
||||||
|
} else {
|
||||||
|
res = cmd.execute(interpreter);
|
||||||
|
}
|
||||||
|
if (res != null && res.startsWith("Error: Unable to establish LAN")) {
|
||||||
|
s_logger.warn("IPMI script timeout(" + cmd.toString() + "), will retry " + retry + " times");
|
||||||
|
continue;
|
||||||
|
} else if (res == null) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.warn("IPMI Scirpt failed due to " + res + "(" + cmd.toString() + ")");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return com.cloud.host.Host.Type.Routing;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected State getVmState() {
|
||||||
|
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
|
||||||
|
if (!doScript(_getStatusCommand, interpreter)) {
|
||||||
|
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (isPowerOn(interpreter.getLines())) {
|
||||||
|
return State.Running;
|
||||||
|
} else {
|
||||||
|
return State.Stopped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, State> fullSync() {
|
||||||
|
Map<String, State> states = new HashMap<String, State>();
|
||||||
|
if (hostId != null) {
|
||||||
|
ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
|
||||||
|
vmDao = locator.getDao(VMInstanceDao.class);
|
||||||
|
final List<? extends VMInstanceVO> vms = vmDao.listByHostId(hostId);
|
||||||
|
for (VMInstanceVO vm : vms) {
|
||||||
|
states.put(vm.getInstanceName(), vm.getState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Map<String, State> changes = new HashMap<String, State>();
|
||||||
|
*
|
||||||
|
* if (_vmName != null) { State state = getVmState(); if (state != null)
|
||||||
|
* { changes.put(_vmName, state); } }
|
||||||
|
*/
|
||||||
|
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StartupCommand[] initialize() {
|
||||||
|
StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, new HashMap<String, String>(), null);
|
||||||
|
cmd.setDataCenter(_zone);
|
||||||
|
cmd.setPod(_pod);
|
||||||
|
cmd.setCluster(_cluster);
|
||||||
|
cmd.setGuid(_uuid);
|
||||||
|
cmd.setName(_ip);
|
||||||
|
cmd.setPrivateIpAddress(_ip);
|
||||||
|
cmd.setStorageIpAddress(_ip);
|
||||||
|
cmd.setVersion(BareMetalResourceBase.class.getPackage().getImplementationVersion());
|
||||||
|
cmd.setCpus((int) _cpuNum);
|
||||||
|
cmd.setSpeed(_cpuCapacity);
|
||||||
|
cmd.setMemory(_memCapacity);
|
||||||
|
cmd.setPrivateMacAddress(_mac);
|
||||||
|
cmd.setPublicMacAddress(_mac);
|
||||||
|
cmd.setStateChanges(fullSync());
|
||||||
|
return new StartupCommand[] { cmd };
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean ipmiPing() {
|
||||||
|
return doScript(_pingCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingCommand getCurrentStatus(long id) {
|
||||||
|
try {
|
||||||
|
if (!ipmiPing()) {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
if (!ipmiPing()) {
|
||||||
|
s_logger.warn("Cannot ping ipmi nic " + _ip);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Cannot ping ipmi nic " + _ip, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PingRoutingCommand(getType(), id, deltaSync());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Answer execute(IpmISetBootDevCommand cmd) {
|
||||||
|
Script bootCmd = null;
|
||||||
|
if (cmd.getBootDev() == BootDev.disk) {
|
||||||
|
bootCmd = _setDiskBootCommand;
|
||||||
|
} else if (cmd.getBootDev() == BootDev.pxe) {
|
||||||
|
bootCmd = _setPxeBootCommand;
|
||||||
|
} else {
|
||||||
|
throw new CloudRuntimeException("Unkonwn boot dev " + cmd.getBootDev());
|
||||||
|
}
|
||||||
|
|
||||||
|
String bootDev = cmd.getBootDev().name();
|
||||||
|
if (!doScript(bootCmd)) {
|
||||||
|
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "failed");
|
||||||
|
return new Answer(cmd, false, "Set " + _ip + " boot dev to " + bootDev + "failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "Success");
|
||||||
|
return new Answer(cmd, true, "Set " + _ip + " boot dev to " + bootDev + "Success");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MaintainAnswer execute(MaintainCommand cmd) {
|
||||||
|
return new MaintainAnswer(cmd, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) {
|
||||||
|
return new PrepareForMigrationAnswer(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MigrateAnswer execute(MigrateCommand cmd) {
|
||||||
|
if (!doScript(_powerOffCommand)) {
|
||||||
|
return new MigrateAnswer(cmd, false, "IPMI power off failed", null);
|
||||||
|
}
|
||||||
|
return new MigrateAnswer(cmd, true, "success", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) {
|
||||||
|
return new CheckVirtualMachineAnswer(cmd, State.Stopped, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Answer execute(IpmiBootorResetCommand cmd) {
|
||||||
|
if (!doScript(_bootOrRebootCommand)) {
|
||||||
|
return new Answer(cmd, false, "IPMI boot or reboot failed");
|
||||||
|
}
|
||||||
|
return new Answer(cmd, true, "Success");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckNetworkAnswer execute(CheckNetworkCommand cmd) {
|
||||||
|
return new CheckNetworkAnswer(cmd, true, "Success");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Answer execute(SecurityGroupRulesCmd cmd) {
|
||||||
|
SecurityGroupHttpClient hc = new SecurityGroupHttpClient();
|
||||||
|
return hc.call(cmd.getGuestIp(), cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer executeRequest(Command cmd) {
|
||||||
|
try {
|
||||||
|
if (cmd instanceof ReadyCommand) {
|
||||||
|
return execute((ReadyCommand) cmd);
|
||||||
|
} else if (cmd instanceof StartCommand) {
|
||||||
|
return execute((StartCommand) cmd);
|
||||||
|
} else if (cmd instanceof StopCommand) {
|
||||||
|
return execute((StopCommand) cmd);
|
||||||
|
} else if (cmd instanceof RebootCommand) {
|
||||||
|
return execute((RebootCommand) cmd);
|
||||||
|
} else if (cmd instanceof IpmISetBootDevCommand) {
|
||||||
|
return execute((IpmISetBootDevCommand) cmd);
|
||||||
|
} else if (cmd instanceof MaintainCommand) {
|
||||||
|
return execute((MaintainCommand) cmd);
|
||||||
|
} else if (cmd instanceof PrepareForMigrationCommand) {
|
||||||
|
return execute((PrepareForMigrationCommand) cmd);
|
||||||
|
} else if (cmd instanceof MigrateCommand) {
|
||||||
|
return execute((MigrateCommand) cmd);
|
||||||
|
} else if (cmd instanceof CheckVirtualMachineCommand) {
|
||||||
|
return execute((CheckVirtualMachineCommand) cmd);
|
||||||
|
} else if (cmd instanceof IpmiBootorResetCommand) {
|
||||||
|
return execute((IpmiBootorResetCommand) cmd);
|
||||||
|
} else if (cmd instanceof SecurityGroupRulesCmd) {
|
||||||
|
return execute((SecurityGroupRulesCmd) cmd);
|
||||||
|
} else if (cmd instanceof CheckNetworkCommand) {
|
||||||
|
return execute((CheckNetworkCommand) cmd);
|
||||||
|
} else {
|
||||||
|
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
s_logger.debug(t.getMessage(), t);
|
||||||
|
return new Answer(cmd, false, t.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isPowerOn(String str) {
|
||||||
|
if (str.startsWith("Chassis Power is on")) {
|
||||||
|
return true;
|
||||||
|
} else if (str.startsWith("Chassis Power is off")) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
throw new CloudRuntimeException("Cannot parse IPMI power status " + str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RebootAnswer execute(final RebootCommand cmd) {
|
||||||
|
if (!doScript(_rebootCommand)) {
|
||||||
|
return new RebootAnswer(cmd, "IPMI reboot failed", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RebootAnswer(cmd, "reboot succeeded", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StopAnswer execute(final StopCommand cmd) {
|
||||||
|
boolean success = false;
|
||||||
|
int count = 0;
|
||||||
|
Script powerOff = _powerOffCommand;
|
||||||
|
|
||||||
|
while (count < 10) {
|
||||||
|
if (!doScript(powerOff)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
|
||||||
|
if (!doScript(_getStatusCommand, interpreter)) {
|
||||||
|
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPowerOn(interpreter.getLines())) {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
powerOff = _forcePowerOffCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success ? new StopAnswer(cmd, "Success", 0, true) : new StopAnswer(cmd, "IPMI power off failed", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StartAnswer execute(StartCommand cmd) {
|
||||||
|
VirtualMachineTO vm = cmd.getVirtualMachine();
|
||||||
|
State state = State.Stopped;
|
||||||
|
|
||||||
|
try {
|
||||||
|
changeVmState(vm.getName(), State.Starting);
|
||||||
|
|
||||||
|
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
|
||||||
|
if (!doScript(_getStatusCommand, interpreter)) {
|
||||||
|
return new StartAnswer(cmd, "Cannot get current power status of " + _name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPowerOn(interpreter.getLines())) {
|
||||||
|
if (!doScript(_rebootCommand)) {
|
||||||
|
return new StartAnswer(cmd, "IPMI reboot failed");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!doScript(_powerOnCommand)) {
|
||||||
|
return new StartAnswer(cmd, "IPMI power on failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isEchoScAgent) {
|
||||||
|
SecurityGroupHttpClient hc = new SecurityGroupHttpClient();
|
||||||
|
boolean echoRet = hc.echo(vm.getNics()[0].getIp(), TimeUnit.MINUTES.toMillis(30), TimeUnit.MINUTES.toMillis(1));
|
||||||
|
if (!echoRet) {
|
||||||
|
return new StartAnswer(cmd, String.format("Call security group agent on vm[%s] timeout", vm.getNics()[0].getIp()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Start bare metal vm " + vm.getName() + "successfully");
|
||||||
|
state = State.Running;
|
||||||
|
_vmName = vm.getName();
|
||||||
|
return new StartAnswer(cmd);
|
||||||
|
} finally {
|
||||||
|
if (state != State.Stopped) {
|
||||||
|
changeVmState(vm.getName(), state);
|
||||||
|
} else {
|
||||||
|
removeVmState(vm.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HashMap<String, State> deltaSync() {
|
||||||
|
final HashMap<String, State> changes = new HashMap<String, State>();
|
||||||
|
/*
|
||||||
|
* Disable sync until we find a way that only tracks status but not does
|
||||||
|
* action
|
||||||
|
*
|
||||||
|
* The scenario is: Baremetal will reboot host when creating template.
|
||||||
|
* Given most servers take a long time to boot up, there would be a
|
||||||
|
* period that mgmt server finds the host is stopped through fullsync.
|
||||||
|
* Then mgmt server updates database with marking the host as stopped,
|
||||||
|
* after that, the host comes up and full sync then indicates it's
|
||||||
|
* running. Because in database the host is already stopped, mgmt server
|
||||||
|
* sends out a stop command. As a result, creating image gets never
|
||||||
|
* happened.
|
||||||
|
*
|
||||||
|
* if (_vmName == null) { return null; }
|
||||||
|
*
|
||||||
|
* State newState = getVmState(); if (newState == null) {
|
||||||
|
* s_logger.warn("Cannot get power state of VM " + _vmName); return
|
||||||
|
* null; }
|
||||||
|
*
|
||||||
|
* final State oldState = removeVmState(_vmName); if (oldState == null)
|
||||||
|
* { changeVmState(_vmName, newState); changes.put(_vmName, newState); }
|
||||||
|
* else if (oldState == State.Starting) { if (newState == State.Running)
|
||||||
|
* { changeVmState(_vmName, newState); } else if (newState ==
|
||||||
|
* State.Stopped) { s_logger.debug("Ignoring vm " + _vmName +
|
||||||
|
* " because of a lag in starting the vm."); } } else if (oldState ==
|
||||||
|
* State.Migrating) {
|
||||||
|
* s_logger.warn("How can baremetal VM get into migrating state???"); }
|
||||||
|
* else if (oldState == State.Stopping) { if (newState == State.Stopped)
|
||||||
|
* { changeVmState(_vmName, newState); } else if (newState ==
|
||||||
|
* State.Running) { s_logger.debug("Ignoring vm " + _vmName +
|
||||||
|
* " because of a lag in stopping the vm. "); } } else if (oldState !=
|
||||||
|
* newState) { changeVmState(_vmName, newState); changes.put(_vmName,
|
||||||
|
* newState); }
|
||||||
|
*/
|
||||||
|
return changes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ReadyAnswer execute(ReadyCommand cmd) {
|
||||||
|
// derived resource should check if the PXE server is ready
|
||||||
|
s_logger.debug("Bare metal resource " + _name + " is ready");
|
||||||
|
return new ReadyAnswer(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnected() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IAgentControl getAgentControl() {
|
||||||
|
return _agentControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAgentControl(IAgentControl agentControl) {
|
||||||
|
_agentControl = agentControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,173 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.dc.DataCenter;
|
||||||
|
import com.cloud.dc.Pod;
|
||||||
|
import com.cloud.dc.PodVlanMapVO;
|
||||||
|
import com.cloud.dc.Vlan;
|
||||||
|
import com.cloud.dc.Vlan.VlanType;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.dc.dao.PodVlanMapDao;
|
||||||
|
import com.cloud.dc.dao.VlanDao;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||||
|
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.network.IPAddressVO;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.NetworkManager;
|
||||||
|
import com.cloud.network.Networks.AddressFormat;
|
||||||
|
import com.cloud.network.Networks.BroadcastDomainType;
|
||||||
|
import com.cloud.network.addr.PublicIp;
|
||||||
|
import com.cloud.network.dao.IPAddressDao;
|
||||||
|
import com.cloud.network.guru.DirectPodBasedNetworkGuru;
|
||||||
|
import com.cloud.network.guru.NetworkGuru;
|
||||||
|
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
@Local(value = { NetworkGuru.class })
|
||||||
|
public class BaremetaNetworkGuru extends DirectPodBasedNetworkGuru {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetaNetworkGuru.class);
|
||||||
|
@Inject
|
||||||
|
private HostDao _hostDao;
|
||||||
|
@Inject
|
||||||
|
DataCenterDao _dcDao;
|
||||||
|
@Inject
|
||||||
|
VlanDao _vlanDao;
|
||||||
|
@Inject
|
||||||
|
NetworkManager _networkMgr;
|
||||||
|
@Inject
|
||||||
|
IPAddressDao _ipAddressDao;
|
||||||
|
@Inject
|
||||||
|
NetworkOfferingDao _networkOfferingDao;
|
||||||
|
@Inject
|
||||||
|
PodVlanMapDao _podVlanDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reserve(NicProfile nic, Network network, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context)
|
||||||
|
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||||
|
if (dest.getHost().getHypervisorType() != HypervisorType.BareMetal) {
|
||||||
|
super.reserve(nic, network, vm, dest, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostVO host = _hostDao.findById(dest.getHost().getId());
|
||||||
|
_hostDao.loadDetails(host);
|
||||||
|
String intentIp = host.getDetail(ApiConstants.IP_ADDRESS);
|
||||||
|
if (intentIp == null) {
|
||||||
|
super.reserve(nic, network, vm, dest, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String oldIp = nic.getIp4Address();
|
||||||
|
boolean getNewIp = false;
|
||||||
|
if (oldIp == null) {
|
||||||
|
getNewIp = true;
|
||||||
|
} else {
|
||||||
|
// we need to get a new ip address if we try to deploy a vm in a
|
||||||
|
// different pod
|
||||||
|
IPAddressVO ipVO = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), oldIp);
|
||||||
|
if (ipVO != null) {
|
||||||
|
PodVlanMapVO mapVO = _podVlanDao.listPodVlanMapsByVlan(ipVO.getVlanId());
|
||||||
|
if (mapVO.getPodId() != dest.getPod().getId()) {
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
|
||||||
|
// release the old ip here
|
||||||
|
_networkMgr.markIpAsUnavailable(ipVO.getId());
|
||||||
|
_ipAddressDao.unassignIpAddress(ipVO.getId());
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
nic.setIp4Address(null);
|
||||||
|
getNewIp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getNewIp) {
|
||||||
|
// we don't set reservationStrategy to Create because we need this
|
||||||
|
// method to be called again for the case when vm fails to deploy in
|
||||||
|
// Pod1, and we try to redeploy it in Pod2
|
||||||
|
getBaremetalIp(nic, dest.getPod(), vm, network, intentIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataCenter dc = _dcDao.findById(network.getDataCenterId());
|
||||||
|
nic.setDns1(dc.getDns1());
|
||||||
|
nic.setDns2(dc.getDns2());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pod pod = dest.getPod(); Pair<String, Long> ip =
|
||||||
|
* _dcDao.allocatePrivateIpAddress(dest.getDataCenter().getId(),
|
||||||
|
* dest.getPod().getId(), nic.getId(), context.getReservationId(),
|
||||||
|
* intentIp); if (ip == null) { throw new
|
||||||
|
* InsufficientAddressCapacityException
|
||||||
|
* ("Unable to get a management ip address", Pod.class, pod.getId()); }
|
||||||
|
*
|
||||||
|
* nic.setIp4Address(ip.first());
|
||||||
|
* nic.setMacAddress(NetUtils.long2Mac(NetUtils
|
||||||
|
* .createSequenceBasedMacAddress(ip.second())));
|
||||||
|
* nic.setGateway(pod.getGateway()); nic.setFormat(AddressFormat.Ip4);
|
||||||
|
* String netmask = NetUtils.getCidrNetmask(pod.getCidrSize());
|
||||||
|
* nic.setNetmask(netmask);
|
||||||
|
* nic.setBroadcastType(BroadcastDomainType.Native);
|
||||||
|
* nic.setBroadcastUri(null); nic.setIsolationUri(null);
|
||||||
|
*/
|
||||||
|
|
||||||
|
s_logger.debug("Allocated a nic " + nic + " for " + vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getBaremetalIp(NicProfile nic, Pod pod, VirtualMachineProfile<? extends VirtualMachine> vm, Network network, String requiredIp)
|
||||||
|
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||||
|
DataCenter dc = _dcDao.findById(pod.getDataCenterId());
|
||||||
|
if (nic.getIp4Address() == null) {
|
||||||
|
s_logger.debug(String.format("Requiring ip address: %s", nic.getIp4Address()));
|
||||||
|
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), pod.getId(), vm.getOwner(), VlanType.DirectAttached, network.getId(), requiredIp, false);
|
||||||
|
nic.setIp4Address(ip.getAddress().toString());
|
||||||
|
nic.setFormat(AddressFormat.Ip4);
|
||||||
|
nic.setGateway(ip.getGateway());
|
||||||
|
nic.setNetmask(ip.getNetmask());
|
||||||
|
if (ip.getVlanTag() != null && ip.getVlanTag().equalsIgnoreCase(Vlan.UNTAGGED)) {
|
||||||
|
nic.setIsolationUri(URI.create("ec2://" + Vlan.UNTAGGED));
|
||||||
|
nic.setBroadcastUri(URI.create("vlan://" + Vlan.UNTAGGED));
|
||||||
|
nic.setBroadcastType(BroadcastDomainType.Native);
|
||||||
|
}
|
||||||
|
nic.setReservationId(String.valueOf(ip.getVlanTag()));
|
||||||
|
nic.setMacAddress(ip.getMacAddress());
|
||||||
|
}
|
||||||
|
nic.setDns1(dc.getDns1());
|
||||||
|
nic.setDns2(dc.getDns2());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.database.BaremetalDhcpVO;
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.dc.Pod;
|
||||||
|
import com.cloud.dc.DataCenter.NetworkType;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||||
|
import com.cloud.network.Network.Capability;
|
||||||
|
import com.cloud.network.Network.GuestType;
|
||||||
|
import com.cloud.network.Network.Provider;
|
||||||
|
import com.cloud.network.Network.Service;
|
||||||
|
import com.cloud.network.Networks.TrafficType;
|
||||||
|
import com.cloud.network.element.DhcpServiceProvider;
|
||||||
|
import com.cloud.network.element.IpDeployer;
|
||||||
|
import com.cloud.network.element.NetworkElement;
|
||||||
|
import com.cloud.offering.NetworkOffering;
|
||||||
|
import com.cloud.utils.component.AdapterBase;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
import com.cloud.utils.db.SearchCriteriaService;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.NicVO;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachine.Type;
|
||||||
|
import com.cloud.vm.dao.NicDao;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
@Local(value = NetworkElement.class)
|
||||||
|
public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProvider {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpElement.class);
|
||||||
|
private static final Map<Service, Map<Capability, String>> capabilities;
|
||||||
|
|
||||||
|
@Inject NicDao _nicDao;
|
||||||
|
@Inject BaremetalDhcpManager _dhcpMgr;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Capability cap = new Capability(BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_CAPABITLITY);
|
||||||
|
Map<Capability, String> baremetalCaps = new HashMap<Capability, String>();
|
||||||
|
baremetalCaps.put(cap, null);
|
||||||
|
capabilities = new HashMap<Service, Map<Capability, String>>();
|
||||||
|
capabilities.put(Service.Dhcp, baremetalCaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Service, Map<Capability, String>> getCapabilities() {
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Provider getProvider() {
|
||||||
|
return BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
|
||||||
|
Pod pod = dest.getPod();
|
||||||
|
if (pod != null && dest.getDataCenter().getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest) {
|
||||||
|
SearchCriteriaService<BaremetalDhcpVO, BaremetalDhcpVO> sc = SearchCriteria2.create(BaremetalDhcpVO.class);
|
||||||
|
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, pod.getId());
|
||||||
|
return sc.find() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
|
||||||
|
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||||
|
if (offering.isSystemOnly() || !canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
|
||||||
|
s_logger.debug("BaremetalDhcpElement can not handle networkoffering: " + offering.getName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DB
|
||||||
|
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
|
||||||
|
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||||
|
Host host = dest.getHost();
|
||||||
|
if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
nic.setMacAddress(host.getPrivateMacAddress());
|
||||||
|
NicVO vo = _nicDao.findById(nic.getId());
|
||||||
|
assert vo != null : "Where ths nic " + nic.getId() + " going???";
|
||||||
|
vo.setMacAddress(nic.getMacAddress());
|
||||||
|
_nicDao.update(vo.getId(), vo);
|
||||||
|
txn.commit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
|
||||||
|
throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady(PhysicalNetworkServiceProvider provider) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
|
||||||
|
ResourceUnavailableException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEnableIndividualServices() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verifyServicesCombination(Set<Service> services) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
|
||||||
|
ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
||||||
|
if (vm.getHypervisorType() != HypervisorType.BareMetal || !canHandle(dest, network.getTrafficType(), network.getGuestType())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _dhcpMgr.addVirtualMachineIntoNetwork(network, nic, vm, dest, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.database.BaremetalDhcpVO;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.Network.Provider;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.component.Manager;
|
||||||
|
import com.cloud.utils.component.PluggableService;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
public interface BaremetalDhcpManager extends Manager, PluggableService {
|
||||||
|
public static enum BaremetalDhcpType {
|
||||||
|
DNSMASQ,
|
||||||
|
DHCPD,
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException;
|
||||||
|
|
||||||
|
BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd);
|
||||||
|
|
||||||
|
BaremetalDhcpResponse generateApiResponse(BaremetalDhcpVO vo);
|
||||||
|
|
||||||
|
List<BaremetalDhcpResponse> listBaremetalDhcps(ListBaremetalDhcpCmd cmd);
|
||||||
|
|
||||||
|
public static final String BAREMETAL_DHCP_SERVICE_CAPABITLITY = "BaremetalDhcp";
|
||||||
|
public static final String BAREMETAL_DHCP_SERVICE_PROPERTIES = "baremetaldhcp_commands.properties";
|
||||||
|
public static final Provider BAREMETAL_DHCP_SERVICE_PROVIDER = new Provider("BaremetalDhcpProvider", true);
|
||||||
|
}
|
||||||
@ -0,0 +1,323 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.AgentManager;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.StartupCommand;
|
||||||
|
import com.cloud.agent.api.StartupExternalDhcpCommand;
|
||||||
|
import com.cloud.agent.api.routing.DhcpEntryCommand;
|
||||||
|
import com.cloud.baremetal.database.BaremetalDhcpDao;
|
||||||
|
import com.cloud.baremetal.database.BaremetalDhcpVO;
|
||||||
|
import com.cloud.dc.DataCenter;
|
||||||
|
import com.cloud.dc.DataCenterVO;
|
||||||
|
import com.cloud.dc.HostPodVO;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.Host.Type;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||||
|
import com.cloud.network.PhysicalNetworkVO;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkDao;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.resource.ResourceStateAdapter;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
import com.cloud.resource.UnableDeleteHostException;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
import com.cloud.utils.db.SearchCriteriaService;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
import com.cloud.vm.dao.NicDao;
|
||||||
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
|
|
||||||
|
@Local(value = { BaremetalDhcpManager.class })
|
||||||
|
public class BaremetalDhcpManagerImpl implements BaremetalDhcpManager, ResourceStateAdapter {
|
||||||
|
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(BaremetalDhcpManagerImpl.class);
|
||||||
|
protected String _name;
|
||||||
|
@Inject
|
||||||
|
DataCenterDao _dcDao;
|
||||||
|
@Inject
|
||||||
|
HostDao _hostDao;
|
||||||
|
@Inject
|
||||||
|
AgentManager _agentMgr;
|
||||||
|
@Inject
|
||||||
|
HostPodDao _podDao;
|
||||||
|
@Inject
|
||||||
|
UserVmDao _userVmDao;
|
||||||
|
@Inject
|
||||||
|
ResourceManager _resourceMgr;
|
||||||
|
@Inject
|
||||||
|
NicDao _nicDao;
|
||||||
|
@Inject
|
||||||
|
PhysicalNetworkDao _physicalNetworkDao;
|
||||||
|
@Inject
|
||||||
|
PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
|
||||||
|
@Inject
|
||||||
|
BaremetalDhcpDao _extDhcpDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDhcpServerGuid(String zoneId, String name, String ip) {
|
||||||
|
return zoneId + "-" + name + "-" + ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile,
|
||||||
|
DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
|
||||||
|
Long zoneId = profile.getVirtualMachine().getDataCenterIdToDeployIn();
|
||||||
|
Long podId = profile.getVirtualMachine().getPodIdToDeployIn();
|
||||||
|
List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Type.BaremetalDhcp, null, podId, zoneId);
|
||||||
|
if (hosts.size() == 0) {
|
||||||
|
throw new CloudRuntimeException("No external Dhcp found in zone " + zoneId + " pod " + podId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hosts.size() > 1) {
|
||||||
|
throw new CloudRuntimeException("Something wrong, more than 1 external Dhcp found in zone " + zoneId + " pod " + podId);
|
||||||
|
}
|
||||||
|
|
||||||
|
HostVO h = hosts.get(0);
|
||||||
|
String dns = nic.getDns1();
|
||||||
|
if (dns == null) {
|
||||||
|
dns = nic.getDns2();
|
||||||
|
}
|
||||||
|
DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), profile.getVirtualMachine().getHostName(), dns,
|
||||||
|
nic.getGateway());
|
||||||
|
String errMsg = String.format("Set dhcp entry on external DHCP %1$s failed(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
|
||||||
|
nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName());
|
||||||
|
// prepareBareMetalDhcpEntry(nic, dhcpCommand);
|
||||||
|
try {
|
||||||
|
Answer ans = _agentMgr.send(h.getId(), dhcpCommand);
|
||||||
|
if (ans.getResult()) {
|
||||||
|
s_logger.debug(String.format("Set dhcp entry on external DHCP %1$s successfully(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
|
||||||
|
nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName()));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
s_logger.debug(errMsg + " " + ans.getDetails());
|
||||||
|
throw new ResourceUnavailableException(errMsg, DataCenter.class, zoneId);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug(errMsg, e);
|
||||||
|
throw new ResourceUnavailableException(errMsg + e.getMessage(), DataCenter.class, zoneId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
|
||||||
|
List<String> hostTags) {
|
||||||
|
if (!(startup[0] instanceof StartupExternalDhcpCommand)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
host.setType(Host.Type.BaremetalDhcp);
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DB
|
||||||
|
public BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd) {
|
||||||
|
PhysicalNetworkVO pNetwork = null;
|
||||||
|
long zoneId;
|
||||||
|
|
||||||
|
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
|
||||||
|
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
|
||||||
|
if (pNetwork == null) {
|
||||||
|
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
|
||||||
|
}
|
||||||
|
zoneId = pNetwork.getDataCenterId();
|
||||||
|
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||||
|
|
||||||
|
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(),
|
||||||
|
BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName());
|
||||||
|
if (ntwkSvcProvider == null) {
|
||||||
|
throw new CloudRuntimeException("Network Service Provider: " + BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName() + " is not enabled in the physical network: "
|
||||||
|
+ cmd.getPhysicalNetworkId() + "to add this device");
|
||||||
|
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
|
||||||
|
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName()
|
||||||
|
+ " is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
|
||||||
|
}
|
||||||
|
|
||||||
|
HostPodVO pod = _podDao.findById(cmd.getPodId());
|
||||||
|
if (pod == null) {
|
||||||
|
throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<HostVO> dhcps = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalDhcp, null, cmd.getPodId(), zoneId);
|
||||||
|
if (dhcps.size() != 0) {
|
||||||
|
throw new IllegalArgumentException("Already had a DHCP server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = new URI(cmd.getUrl());
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug(e);
|
||||||
|
throw new IllegalArgumentException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
String ipAddress = uri.getHost();
|
||||||
|
String guid = getDhcpServerGuid(Long.toString(zoneId) + "-" + Long.toString(cmd.getPodId()), "ExternalDhcp", ipAddress);
|
||||||
|
Map params = new HashMap<String, String>();
|
||||||
|
params.put("type", cmd.getDhcpType());
|
||||||
|
params.put("zone", Long.toString(zoneId));
|
||||||
|
params.put("pod", cmd.getPodId().toString());
|
||||||
|
params.put("ip", ipAddress);
|
||||||
|
params.put("username", cmd.getUsername());
|
||||||
|
params.put("password", cmd.getPassword());
|
||||||
|
params.put("guid", guid);
|
||||||
|
params.put("gateway", pod.getGateway());
|
||||||
|
String dns = zone.getDns1();
|
||||||
|
if (dns == null) {
|
||||||
|
dns = zone.getDns2();
|
||||||
|
}
|
||||||
|
params.put("dns", dns);
|
||||||
|
|
||||||
|
ServerResource resource = null;
|
||||||
|
try {
|
||||||
|
if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DNSMASQ.toString())) {
|
||||||
|
resource = new BaremetalDnsmasqResource();
|
||||||
|
resource.configure("Dnsmasq resource", params);
|
||||||
|
} else if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DHCPD.toString())) {
|
||||||
|
resource = new BaremetalDhcpdResource();
|
||||||
|
resource.configure("Dhcpd resource", params);
|
||||||
|
} else {
|
||||||
|
throw new CloudRuntimeException("Unsupport DHCP server type: " + cmd.getDhcpType());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug(e);
|
||||||
|
throw new CloudRuntimeException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
Host dhcpServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalDhcp, params);
|
||||||
|
if (dhcpServer == null) {
|
||||||
|
throw new CloudRuntimeException("Cannot add external Dhcp server as a host");
|
||||||
|
}
|
||||||
|
|
||||||
|
BaremetalDhcpVO vo = new BaremetalDhcpVO();
|
||||||
|
vo.setDeviceType(cmd.getDhcpType());
|
||||||
|
vo.setHostId(dhcpServer.getId());
|
||||||
|
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
|
||||||
|
vo.setPhysicalNetworkId(cmd.getPhysicalNetworkId());
|
||||||
|
vo.setPodId(cmd.getPodId());
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
_extDhcpDao.persist(vo);
|
||||||
|
txn.commit();
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaremetalDhcpResponse generateApiResponse(BaremetalDhcpVO vo) {
|
||||||
|
BaremetalDhcpResponse response = new BaremetalDhcpResponse();
|
||||||
|
response.setDeviceType(vo.getDeviceType());
|
||||||
|
response.setId(String.valueOf(vo.getId()));
|
||||||
|
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
|
||||||
|
response.setProviderId(String.valueOf(vo.getNetworkServiceProviderId()));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaremetalDhcpResponse> listBaremetalDhcps(ListBaremetalDhcpCmd cmd) {
|
||||||
|
SearchCriteriaService<BaremetalDhcpVO, BaremetalDhcpVO> sc = SearchCriteria2.create(BaremetalDhcpVO.class);
|
||||||
|
if (cmd.getDeviceType() != null) {
|
||||||
|
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, cmd.getDeviceType());
|
||||||
|
}
|
||||||
|
if (cmd.getPodId() != null) {
|
||||||
|
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
|
||||||
|
if (cmd.getId() != null) {
|
||||||
|
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<BaremetalDhcpVO> vos = sc.list();
|
||||||
|
List<BaremetalDhcpResponse> responses = new ArrayList<BaremetalDhcpResponse>(vos.size());
|
||||||
|
for (BaremetalDhcpVO vo : vos) {
|
||||||
|
responses.add(generateApiResponse(vo));
|
||||||
|
}
|
||||||
|
return responses;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Class<?>> getCommands() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.IAgentControl;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
import com.cloud.agent.api.PingRoutingCommand;
|
||||||
|
import com.cloud.agent.api.ReadyAnswer;
|
||||||
|
import com.cloud.agent.api.ReadyCommand;
|
||||||
|
import com.cloud.agent.api.StartupCommand;
|
||||||
|
import com.cloud.agent.api.StartupExternalDhcpCommand;
|
||||||
|
import com.cloud.agent.api.StartupPxeServerCommand;
|
||||||
|
import com.cloud.host.Host.Type;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.trilead.ssh2.SCPClient;
|
||||||
|
|
||||||
|
public class BaremetalDhcpResourceBase implements ServerResource {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpResourceBase.class);
|
||||||
|
String _name;
|
||||||
|
String _guid;
|
||||||
|
String _username;
|
||||||
|
String _password;
|
||||||
|
String _ip;
|
||||||
|
String _zoneId;
|
||||||
|
String _podId;
|
||||||
|
String _gateway;
|
||||||
|
String _dns;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
_name = name;
|
||||||
|
_guid = (String)params.get("guid");
|
||||||
|
_ip = (String)params.get("ip");
|
||||||
|
_username = (String)params.get("username");
|
||||||
|
_password = (String)params.get("password");
|
||||||
|
_zoneId = (String)params.get("zone");
|
||||||
|
_podId = (String)params.get("pod");
|
||||||
|
_gateway = (String)params.get("gateway");
|
||||||
|
_dns = (String)params.get("dns");
|
||||||
|
|
||||||
|
if (_guid == null) {
|
||||||
|
throw new ConfigurationException("No Guid specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zoneId == null) {
|
||||||
|
throw new ConfigurationException("No Zone specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_podId == null) {
|
||||||
|
throw new ConfigurationException("No Pod specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ip == null) {
|
||||||
|
throw new ConfigurationException("No IP specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_username == null) {
|
||||||
|
throw new ConfigurationException("No username specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_password == null) {
|
||||||
|
throw new ConfigurationException("No password specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_gateway == null) {
|
||||||
|
throw new ConfigurationException("No gateway specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dns == null) {
|
||||||
|
throw new ConfigurationException("No dns specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.BaremetalDhcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StartupCommand[] initialize() {
|
||||||
|
StartupExternalDhcpCommand cmd = new StartupExternalDhcpCommand();
|
||||||
|
cmd.setName(_name);
|
||||||
|
cmd.setDataCenter(_zoneId);
|
||||||
|
cmd.setPod(_podId);
|
||||||
|
cmd.setPrivateIpAddress(_ip);
|
||||||
|
cmd.setStorageIpAddress("");
|
||||||
|
cmd.setVersion("");
|
||||||
|
cmd.setGuid(_guid);
|
||||||
|
return new StartupCommand[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingCommand getCurrentStatus(long id) {
|
||||||
|
//TODO: check server
|
||||||
|
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ReadyAnswer execute(ReadyCommand cmd) {
|
||||||
|
s_logger.debug("External DHCP resource " + _name + " is ready");
|
||||||
|
return new ReadyAnswer(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer executeRequest(Command cmd) {
|
||||||
|
if (cmd instanceof ReadyCommand) {
|
||||||
|
return execute((ReadyCommand) cmd);
|
||||||
|
} else {
|
||||||
|
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnected() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IAgentControl getAgentControl() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAgentControl(IAgentControl agentControl) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.BaseResponse;
|
||||||
|
|
||||||
|
import com.cloud.serializer.Param;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class BaremetalDhcpResponse extends BaseResponse {
|
||||||
|
@SerializedName(ApiConstants.ID) @Param(description="device id of ")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this external dhcp device belongs to")
|
||||||
|
private String physicalNetworkId;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
|
||||||
|
private String providerId;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.DHCP_SERVER_TYPE) @Param(description="name of the provider")
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhysicalNetworkId() {
|
||||||
|
return physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhysicalNetworkId(String physicalNetworkId) {
|
||||||
|
this.physicalNetworkId = physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProviderId() {
|
||||||
|
return providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProviderId(String providerId) {
|
||||||
|
this.providerId = providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceType() {
|
||||||
|
return deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceType(String deviceType) {
|
||||||
|
this.deviceType = deviceType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,139 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
import com.cloud.agent.api.PingRoutingCommand;
|
||||||
|
import com.cloud.agent.api.routing.DhcpEntryCommand;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.trilead.ssh2.SCPClient;
|
||||||
|
|
||||||
|
public class BaremetalDhcpdResource extends BaremetalDhcpResourceBase {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpdResource.class);
|
||||||
|
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = null;
|
||||||
|
try {
|
||||||
|
super.configure(name, params);
|
||||||
|
s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, "******"));
|
||||||
|
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dhcpd' ]")) {
|
||||||
|
throw new ConfigurationException("Cannot find dhcpd.conf /etc/dhcpd.conf at on " + _ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCPClient scp = new SCPClient(sshConnection);
|
||||||
|
|
||||||
|
String editHosts = "scripts/network/exdhcp/dhcpd_edithosts.py";
|
||||||
|
String editHostsPath = Script.findScript("", editHosts);
|
||||||
|
if (editHostsPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
|
||||||
|
}
|
||||||
|
scp.put(editHostsPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
String prepareDhcpdScript = "scripts/network/exdhcp/prepare_dhcpd.sh";
|
||||||
|
String prepareDhcpdScriptPath = Script.findScript("", prepareDhcpdScript);
|
||||||
|
if (prepareDhcpdScriptPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find prepare_dhcpd.sh at " + prepareDhcpdScriptPath);
|
||||||
|
}
|
||||||
|
scp.put(prepareDhcpdScriptPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
//TODO: tooooooooooooooo ugly here!!!
|
||||||
|
String[] ips = _ip.split("\\.");
|
||||||
|
ips[3] = "0";
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
int i;
|
||||||
|
for (i=0;i<ips.length-1;i++) {
|
||||||
|
buf.append(ips[i]).append(".");
|
||||||
|
}
|
||||||
|
buf.append(ips[i]);
|
||||||
|
String subnet = buf.toString();
|
||||||
|
String cmd = String.format("sh /usr/bin/prepare_dhcpd.sh %1$s", subnet);
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
|
||||||
|
throw new ConfigurationException("prepare Dhcpd at " + _ip + " failed, command:" + cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Dhcpd resource configure successfully");
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Dhcpd resorce configure failed", e);
|
||||||
|
throw new ConfigurationException(e.getMessage());
|
||||||
|
} finally {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingCommand getCurrentStatus(long id) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Answer execute(DhcpEntryCommand cmd) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = null;
|
||||||
|
try {
|
||||||
|
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
return new Answer(cmd, false, "ssh authenticate failed");
|
||||||
|
}
|
||||||
|
String addDhcp = String.format("python /usr/bin/dhcpd_edithosts.py %1$s %2$s %3$s %4$s %5$s %6$s",
|
||||||
|
cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName(), cmd.getDns(), cmd.getGateway(), cmd.getNextServer());
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
|
||||||
|
return new Answer(cmd, false, "add Dhcp entry failed");
|
||||||
|
} else {
|
||||||
|
return new Answer(cmd);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer executeRequest(Command cmd) {
|
||||||
|
if (cmd instanceof DhcpEntryCommand) {
|
||||||
|
return execute((DhcpEntryCommand)cmd);
|
||||||
|
} else {
|
||||||
|
return super.executeRequest(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
import com.cloud.agent.api.PingRoutingCommand;
|
||||||
|
import com.cloud.agent.api.routing.DhcpEntryCommand;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.trilead.ssh2.SCPClient;
|
||||||
|
|
||||||
|
public class BaremetalDnsmasqResource extends BaremetalDhcpResourceBase {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalDnsmasqResource.class);
|
||||||
|
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = null;
|
||||||
|
try {
|
||||||
|
super.configure(name, params);
|
||||||
|
s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, _password));
|
||||||
|
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, _password));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dnsmasq' ]")) {
|
||||||
|
throw new ConfigurationException("Cannot find dnsmasq at /usr/sbin/dnsmasq on " + _ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCPClient scp = new SCPClient(sshConnection);
|
||||||
|
|
||||||
|
String editHosts = "scripts/network/exdhcp/dnsmasq_edithosts.sh";
|
||||||
|
String editHostsPath = Script.findScript("", editHosts);
|
||||||
|
if (editHostsPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
|
||||||
|
}
|
||||||
|
scp.put(editHostsPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
String prepareDnsmasq = "scripts/network/exdhcp/prepare_dnsmasq.sh";
|
||||||
|
String prepareDnsmasqPath = Script.findScript("", prepareDnsmasq);
|
||||||
|
if (prepareDnsmasqPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find script prepare_dnsmasq.sh at " + prepareDnsmasq);
|
||||||
|
}
|
||||||
|
scp.put(prepareDnsmasqPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
String prepareCmd = String.format("sh /usr/bin/prepare_dnsmasq.sh %1$s %2$s %3$s", _gateway, _dns, _ip);
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, prepareCmd)) {
|
||||||
|
throw new ConfigurationException("prepare dnsmasq at " + _ip + " failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Dnsmasq resource configure successfully");
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Dnsmasq resorce configure failed", e);
|
||||||
|
throw new ConfigurationException(e.getMessage());
|
||||||
|
} finally {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingCommand getCurrentStatus(long id) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Answer execute(DhcpEntryCommand cmd) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = null;
|
||||||
|
try {
|
||||||
|
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
return new Answer(cmd, false, "ssh authenticate failed");
|
||||||
|
}
|
||||||
|
String addDhcp = String.format("/usr/bin/dnsmasq_edithosts.sh %1$s %2$s %3$s", cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName());
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
|
||||||
|
return new Answer(cmd, false, "add Dhcp entry failed");
|
||||||
|
} else {
|
||||||
|
return new Answer(cmd);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer executeRequest(Command cmd) {
|
||||||
|
if (cmd instanceof DhcpEntryCommand) {
|
||||||
|
return execute((DhcpEntryCommand)cmd);
|
||||||
|
} else {
|
||||||
|
return super.executeRequest(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,201 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
import com.cloud.agent.api.PingRoutingCommand;
|
||||||
|
import com.cloud.agent.api.routing.VmDataCommand;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.trilead.ssh2.SCPClient;
|
||||||
|
|
||||||
|
public class BaremetalKickStartPxeResource extends BaremetalPxeResourceBase {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalKickStartPxeResource.class);
|
||||||
|
private static final String _name = "BaremetalKickStartPxeResource";
|
||||||
|
String _tftpDir;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
super.configure(name, params);
|
||||||
|
_tftpDir = (String) params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
|
||||||
|
if (_tftpDir == null) {
|
||||||
|
throw new ConfigurationException("No tftp directory specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||||
|
|
||||||
|
s_logger.debug(String.format("Trying to connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
|
||||||
|
try {
|
||||||
|
sshConnection.connect(null, 60000, 60000);
|
||||||
|
if (!sshConnection.authenticateWithPassword(_username, _password)) {
|
||||||
|
s_logger.debug("SSH Failed to authenticate");
|
||||||
|
throw new ConfigurationException(String.format("Cannot connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||||
|
"******"));
|
||||||
|
}
|
||||||
|
|
||||||
|
String cmd = String.format("[ -f /%1$s/pxelinux.0 ]", _tftpDir);
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
|
||||||
|
throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0 are here");
|
||||||
|
}
|
||||||
|
|
||||||
|
SCPClient scp = new SCPClient(sshConnection);
|
||||||
|
String prepareScript = "scripts/network/ping/prepare_kickstart_bootfile.py";
|
||||||
|
String prepareScriptPath = Script.findScript("", prepareScript);
|
||||||
|
if (prepareScriptPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find prepare_kickstart_bootfile.py at " + prepareScriptPath);
|
||||||
|
}
|
||||||
|
scp.put(prepareScriptPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
String cpScript = "scripts/network/ping/prepare_kickstart_kernel_initrd.py";
|
||||||
|
String cpScriptPath = Script.findScript("", cpScript);
|
||||||
|
if (cpScriptPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find prepare_kickstart_kernel_initrd.py at " + cpScriptPath);
|
||||||
|
}
|
||||||
|
scp.put(cpScriptPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
String userDataScript = "scripts/network/ping/baremetal_user_data.py";
|
||||||
|
String userDataScriptPath = Script.findScript("", userDataScript);
|
||||||
|
if (userDataScriptPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
|
||||||
|
}
|
||||||
|
scp.put(userDataScriptPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ConfigurationException(e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sshConnection != null) {
|
||||||
|
sshConnection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingCommand getCurrentStatus(long id) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Answer execute(VmDataCommand cmd) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||||
|
try {
|
||||||
|
List<String[]> vmData = cmd.getVmData();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String[] data : vmData) {
|
||||||
|
String folder = data[0];
|
||||||
|
String file = data[1];
|
||||||
|
String contents = (data[2] == null) ? "none" : data[2];
|
||||||
|
sb.append(cmd.getVmIpAddress());
|
||||||
|
sb.append(",");
|
||||||
|
sb.append(folder);
|
||||||
|
sb.append(",");
|
||||||
|
sb.append(file);
|
||||||
|
sb.append(",");
|
||||||
|
sb.append(contents);
|
||||||
|
sb.append(";");
|
||||||
|
}
|
||||||
|
String arg = StringUtils.stripEnd(sb.toString(), ";");
|
||||||
|
|
||||||
|
sshConnection.connect(null, 60000, 60000);
|
||||||
|
if (!sshConnection.authenticateWithPassword(_username, _password)) {
|
||||||
|
s_logger.debug("SSH Failed to authenticate");
|
||||||
|
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||||
|
_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
|
||||||
|
return new Answer(cmd, false, "Failed to add user data, command:" + script);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Answer(cmd, true, "Success");
|
||||||
|
} catch (Exception e){
|
||||||
|
s_logger.debug("Prepare for creating baremetal template failed", e);
|
||||||
|
return new Answer(cmd, false, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sshConnection != null) {
|
||||||
|
sshConnection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer executeRequest(Command cmd) {
|
||||||
|
if (cmd instanceof PrepareKickstartPxeServerCommand) {
|
||||||
|
return execute((PrepareKickstartPxeServerCommand) cmd);
|
||||||
|
} else if (cmd instanceof VmDataCommand) {
|
||||||
|
return execute((VmDataCommand)cmd);
|
||||||
|
} else {
|
||||||
|
return super.executeRequest(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Answer execute(PrepareKickstartPxeServerCommand cmd) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||||
|
try {
|
||||||
|
sshConnection.connect(null, 60000, 60000);
|
||||||
|
if (!sshConnection.authenticateWithPassword(_username, _password)) {
|
||||||
|
s_logger.debug("SSH Failed to authenticate");
|
||||||
|
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||||
|
_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
String copyTo = String.format("%s/%s", _tftpDir, cmd.getTemplateUuid());
|
||||||
|
String script = String.format("python /usr/bin/prepare_kickstart_kernel_initrd.py %s %s", cmd.getRepo(), copyTo);
|
||||||
|
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
|
||||||
|
return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
|
||||||
|
}
|
||||||
|
|
||||||
|
String kernelPath = String.format("%s/vmlinuz", cmd.getTemplateUuid());
|
||||||
|
String initrdPath = String.format("%s/initrd.img", cmd.getTemplateUuid());
|
||||||
|
script = String.format("python /usr/bin/prepare_kickstart_bootfile.py %s %s %s %s %s %s", _tftpDir, cmd.getMac(), kernelPath, initrdPath, cmd.getKsFile(), cmd.getMac());
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
|
||||||
|
return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Prepare kickstart PXE server successfully");
|
||||||
|
return new Answer(cmd, true, "Success");
|
||||||
|
} catch (Exception e){
|
||||||
|
s_logger.debug("Prepare for kickstart server failed", e);
|
||||||
|
return new Answer(cmd, false, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sshConnection != null) {
|
||||||
|
sshConnection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,238 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
|
||||||
|
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeDao;
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDetailsDao;
|
||||||
|
import com.cloud.network.NetworkVO;
|
||||||
|
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||||
|
import com.cloud.network.PhysicalNetworkVO;
|
||||||
|
import com.cloud.network.dao.NetworkDao;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkDao;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
import com.cloud.storage.VMTemplateVO;
|
||||||
|
import com.cloud.storage.dao.VMTemplateDao;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
import com.cloud.utils.db.SearchCriteriaService;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
@Local(value = BaremetalPxeService.class)
|
||||||
|
public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalKickStartServiceImpl.class);
|
||||||
|
@Inject
|
||||||
|
ResourceManager _resourceMgr;
|
||||||
|
@Inject
|
||||||
|
PhysicalNetworkDao _physicalNetworkDao;
|
||||||
|
@Inject
|
||||||
|
PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
|
||||||
|
@Inject
|
||||||
|
HostDetailsDao _hostDetailsDao;
|
||||||
|
@Inject
|
||||||
|
BaremetalPxeDao _pxeDao;
|
||||||
|
@Inject
|
||||||
|
NetworkDao _nwDao;
|
||||||
|
@Inject
|
||||||
|
VMTemplateDao _tmpDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile nic, DeployDestination dest, ReservationContext context) {
|
||||||
|
NetworkVO nwVO = _nwDao.findById(nic.getNetworkId());
|
||||||
|
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
|
||||||
|
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
|
||||||
|
sc.addAnd(sc.getEntity().getPhysicalNetworkId(), Op.EQ, nwVO.getPhysicalNetworkId());
|
||||||
|
BaremetalPxeVO pxeVo = sc.find();
|
||||||
|
if (pxeVo == null) {
|
||||||
|
throw new CloudRuntimeException("No kickstart PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM");
|
||||||
|
}
|
||||||
|
VMTemplateVO template = _tmpDao.findById(profile.getTemplateId());
|
||||||
|
|
||||||
|
try {
|
||||||
|
String tpl = profile.getTemplate().getUrl();
|
||||||
|
assert tpl != null : "How can a null template get here!!!";
|
||||||
|
String[] tpls = tpl.split(";");
|
||||||
|
assert tpls.length == 2 : "Template is not correctly encoded. " + tpl;
|
||||||
|
PrepareKickstartPxeServerCommand cmd = new PrepareKickstartPxeServerCommand();
|
||||||
|
cmd.setKsFile(tpls[0]);
|
||||||
|
cmd.setRepo(tpls[1]);
|
||||||
|
cmd.setMac(nic.getMacAddress());
|
||||||
|
cmd.setTemplateUuid(template.getUuid());
|
||||||
|
Answer aws = _agentMgr.send(pxeVo.getHostId(), cmd);
|
||||||
|
if (!aws.getResult()) {
|
||||||
|
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
|
||||||
|
return aws.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
|
||||||
|
aws = _agentMgr.send(dest.getHost().getId(), bootCmd);
|
||||||
|
if (!aws.getResult()) {
|
||||||
|
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
|
||||||
|
}
|
||||||
|
|
||||||
|
return aws.getResult();
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.warn("Cannot prepare PXE server", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DB
|
||||||
|
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
|
||||||
|
AddBaremetalKickStartPxeCmd kcmd = (AddBaremetalKickStartPxeCmd)cmd;
|
||||||
|
PhysicalNetworkVO pNetwork = null;
|
||||||
|
long zoneId;
|
||||||
|
|
||||||
|
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
|
||||||
|
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
|
||||||
|
if (pNetwork == null) {
|
||||||
|
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
|
||||||
|
}
|
||||||
|
zoneId = pNetwork.getDataCenterId();
|
||||||
|
|
||||||
|
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
|
||||||
|
if (ntwkSvcProvider == null) {
|
||||||
|
throw new CloudRuntimeException("Network Service Provider: " + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName() +
|
||||||
|
" is not enabled in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
|
||||||
|
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
|
||||||
|
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
|
||||||
|
" is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<HostVO> pxes = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId);
|
||||||
|
if (!pxes.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Already had a PXE server zone: " + zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
String tftpDir = kcmd.getTftpDir();
|
||||||
|
if (tftpDir == null) {
|
||||||
|
throw new IllegalArgumentException("No TFTP directory specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = new URI(cmd.getUrl());
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug(e);
|
||||||
|
throw new IllegalArgumentException(e.getMessage());
|
||||||
|
}
|
||||||
|
String ipAddress = uri.getHost();
|
||||||
|
|
||||||
|
String guid = getPxeServerGuid(Long.toString(zoneId), BaremetalPxeType.KICK_START.toString(), ipAddress);
|
||||||
|
|
||||||
|
ServerResource resource = null;
|
||||||
|
Map params = new HashMap<String, String>();
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
|
||||||
|
params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
|
||||||
|
resource = new BaremetalKickStartPxeResource();
|
||||||
|
try {
|
||||||
|
resource.configure("KickStart PXE resource", params);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CloudRuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
|
||||||
|
if (pxeServer == null) {
|
||||||
|
throw new CloudRuntimeException("Cannot add PXE server as a host");
|
||||||
|
}
|
||||||
|
|
||||||
|
BaremetalPxeVO vo = new BaremetalPxeVO();
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
vo.setHostId(pxeServer.getId());
|
||||||
|
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
|
||||||
|
vo.setPhysicalNetworkId(kcmd.getPhysicalNetworkId());
|
||||||
|
vo.setDeviceType(BaremetalPxeType.KICK_START.toString());
|
||||||
|
txn.start();
|
||||||
|
_pxeDao.persist(vo);
|
||||||
|
txn.commit();
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
|
||||||
|
BaremetalPxeKickStartResponse response = new BaremetalPxeKickStartResponse();
|
||||||
|
response.setId(String.valueOf(vo.getId()));
|
||||||
|
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
|
||||||
|
response.setPodId(String.valueOf(vo.getPodId()));
|
||||||
|
Map<String, String> details = _hostDetailsDao.findDetails(vo.getHostId());
|
||||||
|
response.setTftpDir(details.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
|
||||||
|
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
|
||||||
|
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
|
||||||
|
if (cmd.getPodId() != null) {
|
||||||
|
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
|
||||||
|
if (cmd.getId() != null) {
|
||||||
|
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<BaremetalPxeVO> vos = sc.list();
|
||||||
|
List<BaremetalPxeResponse> responses = new ArrayList<BaremetalPxeResponse>(vos.size());
|
||||||
|
for (BaremetalPxeVO vo : vos) {
|
||||||
|
responses.add(getApiResponse(vo));
|
||||||
|
}
|
||||||
|
return responses;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,260 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
import com.cloud.agent.api.PingRoutingCommand;
|
||||||
|
import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
|
||||||
|
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
|
||||||
|
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
|
||||||
|
import com.cloud.agent.api.routing.VmDataCommand;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.trilead.ssh2.SCPClient;
|
||||||
|
|
||||||
|
public class BaremetalPingPxeResource extends BaremetalPxeResourceBase {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalPingPxeResource.class);
|
||||||
|
private static final String _name = "BaremetalPingPxeResource";
|
||||||
|
String _storageServer;
|
||||||
|
String _pingDir;
|
||||||
|
String _share;
|
||||||
|
String _dir;
|
||||||
|
String _tftpDir;
|
||||||
|
String _cifsUserName;
|
||||||
|
String _cifsPassword;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
super.configure(name, params);
|
||||||
|
_storageServer = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP);
|
||||||
|
_pingDir = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR);
|
||||||
|
_tftpDir = (String)params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
|
||||||
|
_cifsUserName = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME);
|
||||||
|
_cifsPassword = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD);
|
||||||
|
|
||||||
|
if (_podId == null) {
|
||||||
|
throw new ConfigurationException("No Pod specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_storageServer == null) {
|
||||||
|
throw new ConfigurationException("No stroage server specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_tftpDir == null) {
|
||||||
|
throw new ConfigurationException("No tftp directory specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pingDir == null) {
|
||||||
|
throw new ConfigurationException("No PING directory specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cifsUserName == null || _cifsUserName.equalsIgnoreCase("")) {
|
||||||
|
_cifsUserName = "xxx";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cifsPassword == null || _cifsPassword.equalsIgnoreCase("")) {
|
||||||
|
_cifsPassword = "xxx";
|
||||||
|
}
|
||||||
|
|
||||||
|
String pingDirs[]= _pingDir.split("/");
|
||||||
|
if (pingDirs.length != 2) {
|
||||||
|
throw new ConfigurationException("PING dir should have format like myshare/direcotry, eg: windows/64bit");
|
||||||
|
}
|
||||||
|
_share = pingDirs[0];
|
||||||
|
_dir = pingDirs[1];
|
||||||
|
|
||||||
|
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||||
|
|
||||||
|
s_logger.debug(String.format("Trying to connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
|
||||||
|
try {
|
||||||
|
sshConnection.connect(null, 60000, 60000);
|
||||||
|
if (!sshConnection.authenticateWithPassword(_username, _password)) {
|
||||||
|
s_logger.debug("SSH Failed to authenticate");
|
||||||
|
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||||
|
"******"));
|
||||||
|
}
|
||||||
|
|
||||||
|
String cmd = String.format("[ -f /%1$s/pxelinux.0 ] && [ -f /%2$s/kernel ] && [ -f /%3$s/initrd.gz ] ", _tftpDir, _tftpDir, _tftpDir);
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
|
||||||
|
throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0, kernel initrd.gz are here");
|
||||||
|
}
|
||||||
|
|
||||||
|
SCPClient scp = new SCPClient(sshConnection);
|
||||||
|
String prepareScript = "scripts/network/ping/prepare_tftp_bootfile.py";
|
||||||
|
String prepareScriptPath = Script.findScript("", prepareScript);
|
||||||
|
if (prepareScriptPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find prepare_tftp_bootfile.py at " + prepareScriptPath);
|
||||||
|
}
|
||||||
|
scp.put(prepareScriptPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
String userDataScript = "scripts/network/ping/baremetal_user_data.py";
|
||||||
|
String userDataScriptPath = Script.findScript("", userDataScript);
|
||||||
|
if (userDataScriptPath == null) {
|
||||||
|
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
|
||||||
|
}
|
||||||
|
scp.put(userDataScriptPath, "/usr/bin/", "0755");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ConfigurationException(e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sshConnection != null) {
|
||||||
|
sshConnection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingCommand getCurrentStatus(long id) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
|
||||||
|
if (sshConnection == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
SSHCmdHelper.releaseSshConnection(sshConnection);
|
||||||
|
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PreparePxeServerAnswer execute(PreparePxeServerCommand cmd) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||||
|
try {
|
||||||
|
sshConnection.connect(null, 60000, 60000);
|
||||||
|
if (!sshConnection.authenticateWithPassword(_username, _password)) {
|
||||||
|
s_logger.debug("SSH Failed to authenticate");
|
||||||
|
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||||
|
_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
String script = String.format("python /usr/bin/prepare_tftp_bootfile.py restore %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
|
||||||
|
_tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
|
||||||
|
return new PreparePxeServerAnswer(cmd, "prepare PING at " + _ip + " failed, command:" + script);
|
||||||
|
}
|
||||||
|
s_logger.debug("Prepare Ping PXE server successfully");
|
||||||
|
|
||||||
|
return new PreparePxeServerAnswer(cmd);
|
||||||
|
} catch (Exception e){
|
||||||
|
s_logger.debug("Prepare PING pxe server failed", e);
|
||||||
|
return new PreparePxeServerAnswer(cmd, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sshConnection != null) {
|
||||||
|
sshConnection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Answer execute(prepareCreateTemplateCommand cmd) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||||
|
try {
|
||||||
|
sshConnection.connect(null, 60000, 60000);
|
||||||
|
if (!sshConnection.authenticateWithPassword(_username, _password)) {
|
||||||
|
s_logger.debug("SSH Failed to authenticate");
|
||||||
|
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||||
|
_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
String script = String.format("python /usr/bin/prepare_tftp_bootfile.py backup %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
|
||||||
|
_tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
|
||||||
|
return new Answer(cmd, false, "prepare for creating template failed, command:" + script);
|
||||||
|
}
|
||||||
|
s_logger.debug("Prepare for creating template successfully");
|
||||||
|
|
||||||
|
return new Answer(cmd, true, "Success");
|
||||||
|
} catch (Exception e){
|
||||||
|
s_logger.debug("Prepare for creating baremetal template failed", e);
|
||||||
|
return new Answer(cmd, false, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sshConnection != null) {
|
||||||
|
sshConnection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer executeRequest(Command cmd) {
|
||||||
|
if (cmd instanceof PreparePxeServerCommand) {
|
||||||
|
return execute((PreparePxeServerCommand) cmd);
|
||||||
|
} else if (cmd instanceof prepareCreateTemplateCommand) {
|
||||||
|
return execute((prepareCreateTemplateCommand)cmd);
|
||||||
|
} else if (cmd instanceof VmDataCommand) {
|
||||||
|
return execute((VmDataCommand)cmd);
|
||||||
|
} else {
|
||||||
|
return super.executeRequest(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Answer execute(VmDataCommand cmd) {
|
||||||
|
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||||
|
try {
|
||||||
|
List<String[]> vmData = cmd.getVmData();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String[] data : vmData) {
|
||||||
|
String folder = data[0];
|
||||||
|
String file = data[1];
|
||||||
|
String contents = (data[2] == null) ? "none" : data[2];
|
||||||
|
sb.append(cmd.getVmIpAddress());
|
||||||
|
sb.append(",");
|
||||||
|
sb.append(folder);
|
||||||
|
sb.append(",");
|
||||||
|
sb.append(file);
|
||||||
|
sb.append(",");
|
||||||
|
sb.append(contents);
|
||||||
|
sb.append(";");
|
||||||
|
}
|
||||||
|
String arg = org.apache.commons.lang.StringUtils.stripEnd(sb.toString(), ";");
|
||||||
|
|
||||||
|
sshConnection.connect(null, 60000, 60000);
|
||||||
|
if (!sshConnection.authenticateWithPassword(_username, _password)) {
|
||||||
|
s_logger.debug("SSH Failed to authenticate");
|
||||||
|
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||||
|
_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
|
||||||
|
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
|
||||||
|
return new Answer(cmd, false, "Failed to add user data, command:" + script);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Answer(cmd, true, "Success");
|
||||||
|
} catch (Exception e){
|
||||||
|
s_logger.debug("Prepare for creating baremetal template failed", e);
|
||||||
|
return new Answer(cmd, false, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sshConnection != null) {
|
||||||
|
sshConnection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.dc.DataCenter.NetworkType;
|
||||||
|
import com.cloud.dc.Pod;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.Network.Capability;
|
||||||
|
import com.cloud.network.Network.GuestType;
|
||||||
|
import com.cloud.network.Network.Provider;
|
||||||
|
import com.cloud.network.Network.Service;
|
||||||
|
import com.cloud.network.Networks.TrafficType;
|
||||||
|
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||||
|
import com.cloud.network.element.NetworkElement;
|
||||||
|
import com.cloud.offering.NetworkOffering;
|
||||||
|
import com.cloud.utils.component.AdapterBase;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
import com.cloud.utils.db.SearchCriteriaService;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.NicVO;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.VMInstanceVO;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachine.Type;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
import com.cloud.vm.dao.NicDao;
|
||||||
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
|
|
||||||
|
@Local(value = NetworkElement.class)
|
||||||
|
public class BaremetalPxeElement extends AdapterBase implements NetworkElement {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalPxeElement.class);
|
||||||
|
private static final Map<Service, Map<Capability, String>> capabilities;
|
||||||
|
|
||||||
|
@Inject BaremetalPxeManager _pxeMgr;;
|
||||||
|
@Inject VMInstanceDao _vmDao;
|
||||||
|
@Inject NicDao _nicDao;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Capability cap = new Capability(BaremetalPxeManager.BAREMETAL_PXE_CAPABILITY);
|
||||||
|
Map<Capability, String> baremetalCaps = new HashMap<Capability, String>();
|
||||||
|
baremetalCaps.put(cap, null);
|
||||||
|
capabilities = new HashMap<Service, Map<Capability, String>>();
|
||||||
|
capabilities.put(BaremetalPxeManager.BAREMETAL_PXE_SERVICE, baremetalCaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Service, Map<Capability, String>> getCapabilities() {
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Provider getProvider() {
|
||||||
|
return BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
|
||||||
|
Pod pod = dest.getPod();
|
||||||
|
if (pod != null && dest.getDataCenter().getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest) {
|
||||||
|
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
|
||||||
|
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, pod.getId());
|
||||||
|
return sc.find() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
|
||||||
|
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||||
|
if (offering.isSystemOnly() || !canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
|
||||||
|
s_logger.debug("BaremetalPxeElement can not handle network offering: " + offering.getName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DB
|
||||||
|
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
|
||||||
|
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||||
|
if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMInstanceVO vo = _vmDao.findById(vm.getId());
|
||||||
|
if (vo.getLastHostId() == null) {
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
nic.setMacAddress(dest.getHost().getPrivateMacAddress());
|
||||||
|
NicVO nicVo = _nicDao.findById(nic.getId());
|
||||||
|
assert vo != null : "Where ths nic " + nic.getId() + " going???";
|
||||||
|
nicVo.setMacAddress(nic.getMacAddress());
|
||||||
|
_nicDao.update(nicVo.getId(), nicVo);
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
/*This vm is just being created */
|
||||||
|
if (!_pxeMgr.prepare(vm, nic, dest, context)) {
|
||||||
|
throw new CloudRuntimeException("Cannot prepare pxe server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
|
||||||
|
throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady(PhysicalNetworkServiceProvider provider) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
|
||||||
|
ResourceUnavailableException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEnableIndividualServices() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verifyServicesCombination(Set<Service> services) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
|
||||||
|
import com.cloud.serializer.Param;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class BaremetalPxeKickStartResponse extends BaremetalPxeResponse {
|
||||||
|
@SerializedName(ApiConstants.TFTP_DIR) @Param(description="Tftp root directory of PXE server")
|
||||||
|
private String tftpDir;
|
||||||
|
|
||||||
|
public String getTftpDir() {
|
||||||
|
return tftpDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTftpDir(String tftpDir) {
|
||||||
|
this.tftpDir = tftpDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.Network.Provider;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.component.Manager;
|
||||||
|
import com.cloud.utils.component.PluggableService;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
public interface BaremetalPxeManager extends Manager, PluggableService {
|
||||||
|
public enum BaremetalPxeType {
|
||||||
|
PING,
|
||||||
|
KICK_START,
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context);
|
||||||
|
|
||||||
|
boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
|
||||||
|
|
||||||
|
BaremetalPxeType getPxeServerType(HostVO host);
|
||||||
|
|
||||||
|
BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd);
|
||||||
|
|
||||||
|
BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo);
|
||||||
|
|
||||||
|
List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
|
||||||
|
|
||||||
|
boolean addUserData(NicProfile nic, VirtualMachineProfile<UserVm> vm);
|
||||||
|
|
||||||
|
public static final Network.Service BAREMETAL_PXE_SERVICE = new Network.Service("BaremetalPxeService");
|
||||||
|
public static final String BAREMETAL_PXE_CAPABILITY = "BaremetalPxe";
|
||||||
|
public static final String BAREMETAL_PXE_SERVICE_PROPERTIES = "baremetalpxe_commands.properties";
|
||||||
|
public static final Provider BAREMETAL_PXE_SERVICE_PROVIDER = new Provider("BaremetalPxeProvider", true);;
|
||||||
|
public static final Provider BAREMETAL_USERDATA_PROVIDER = new Provider("BaremetaUserdataProvider", true);
|
||||||
|
}
|
||||||
@ -0,0 +1,242 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.AgentManager;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.StartupCommand;
|
||||||
|
import com.cloud.agent.api.StartupPxeServerCommand;
|
||||||
|
import com.cloud.agent.api.routing.VmDataCommand;
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.configuration.dao.ConfigurationDao;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.network.PhysicalNetworkVO;
|
||||||
|
import com.cloud.network.dao.PhysicalNetworkDao;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.resource.ResourceStateAdapter;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
import com.cloud.resource.UnableDeleteHostException;
|
||||||
|
import com.cloud.service.dao.ServiceOfferingDao;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.StringUtils;
|
||||||
|
import com.cloud.utils.component.Adapters;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
|
import com.cloud.utils.db.SearchCriteria2;
|
||||||
|
import com.cloud.utils.db.SearchCriteriaService;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.NicVO;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
import com.cloud.vm.dao.NicDao;
|
||||||
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
|
|
||||||
|
@Local(value = {BaremetalPxeManager.class})
|
||||||
|
public class BaremetalPxeManagerImpl implements BaremetalPxeManager, ResourceStateAdapter {
|
||||||
|
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(BaremetalPxeManagerImpl.class);
|
||||||
|
protected String _name;
|
||||||
|
@Inject DataCenterDao _dcDao;
|
||||||
|
@Inject HostDao _hostDao;
|
||||||
|
@Inject AgentManager _agentMgr;
|
||||||
|
@Inject ResourceManager _resourceMgr;
|
||||||
|
@Inject(adapter=BaremetalPxeService.class)
|
||||||
|
protected Adapters<BaremetalPxeService> _services;
|
||||||
|
@Inject UserVmDao _vmDao;
|
||||||
|
@Inject ServiceOfferingDao _serviceOfferingDao;
|
||||||
|
@Inject NicDao _nicDao;
|
||||||
|
@Inject ConfigurationDao _configDao;
|
||||||
|
@Inject PhysicalNetworkDao _phynwDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
_name = name;
|
||||||
|
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BaremetalPxeService getServiceByType(String type) {
|
||||||
|
BaremetalPxeService _service;
|
||||||
|
_service = _services.get(type);
|
||||||
|
if (_service == null) {
|
||||||
|
throw new CloudRuntimeException("Cannot find PXE service for " + type);
|
||||||
|
}
|
||||||
|
return _service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) {
|
||||||
|
//TODO: select type from template
|
||||||
|
BaremetalPxeType type = BaremetalPxeType.KICK_START;
|
||||||
|
return getServiceByType(type.toString()).prepare(profile, nic, dest, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
|
||||||
|
//TODO: select type from template
|
||||||
|
BaremetalPxeType type = BaremetalPxeType.PING;
|
||||||
|
return getServiceByType(type.toString()).prepareCreateTemplate(pxeServerId, vm, templateUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaremetalPxeType getPxeServerType(HostVO host) {
|
||||||
|
if (host.getResource().equalsIgnoreCase(BaremetalPingPxeResource.class.getName())) {
|
||||||
|
return BaremetalPxeType.PING;
|
||||||
|
} else {
|
||||||
|
throw new CloudRuntimeException("Unkown PXE server resource " + host.getResource());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
|
||||||
|
List<String> hostTags) {
|
||||||
|
if (!(startup[0] instanceof StartupPxeServerCommand)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
host.setType(Host.Type.BaremetalPxe);
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
|
||||||
|
return getServiceByType(cmd.getDeviceType()).addPxeServer(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
|
||||||
|
return getServiceByType(vo.getDeviceType()).getApiResponse(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
|
||||||
|
return getServiceByType(BaremetalPxeManager.BaremetalPxeType.PING.toString()).listPxeServers(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addUserData(NicProfile nic, VirtualMachineProfile<UserVm> profile) {
|
||||||
|
UserVmVO vm = (UserVmVO) profile.getVirtualMachine();
|
||||||
|
_vmDao.loadDetails(vm);
|
||||||
|
|
||||||
|
String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()).getDisplayText();
|
||||||
|
String zoneName = _dcDao.findById(vm.getDataCenterIdToDeployIn()).getName();
|
||||||
|
NicVO nvo = _nicDao.findById(nic.getId());
|
||||||
|
VmDataCommand cmd = new VmDataCommand(nvo.getIp4Address(), vm.getInstanceName());
|
||||||
|
cmd.addVmData("userdata", "user-data", vm.getUserData());
|
||||||
|
cmd.addVmData("metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering));
|
||||||
|
cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName));
|
||||||
|
cmd.addVmData("metadata", "local-ipv4", nic.getIp4Address());
|
||||||
|
cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
|
||||||
|
cmd.addVmData("metadata", "public-ipv4", nic.getIp4Address());
|
||||||
|
cmd.addVmData("metadata", "public-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
|
||||||
|
cmd.addVmData("metadata", "instance-id", String.valueOf(vm.getId()));
|
||||||
|
cmd.addVmData("metadata", "vm-id", String.valueOf(vm.getInstanceName()));
|
||||||
|
cmd.addVmData("metadata", "public-keys", null);
|
||||||
|
String cloudIdentifier = _configDao.getValue("cloud.identifier");
|
||||||
|
if (cloudIdentifier == null) {
|
||||||
|
cloudIdentifier = "";
|
||||||
|
} else {
|
||||||
|
cloudIdentifier = "CloudStack-{" + cloudIdentifier + "}";
|
||||||
|
}
|
||||||
|
cmd.addVmData("metadata", "cloud-identifier", cloudIdentifier);
|
||||||
|
|
||||||
|
List<PhysicalNetworkVO> phys = _phynwDao.listByZone(vm.getDataCenterIdToDeployIn());
|
||||||
|
if (phys.isEmpty()) {
|
||||||
|
throw new CloudRuntimeException(String.format("Cannot find physical network in zone %s", vm.getDataCenterIdToDeployIn()));
|
||||||
|
}
|
||||||
|
if (phys.size() > 1) {
|
||||||
|
throw new CloudRuntimeException(String.format("Baremetal only supports one physical network in zone, but zone %s has %s physical networks", vm.getDataCenterIdToDeployIn(), phys.size()));
|
||||||
|
}
|
||||||
|
PhysicalNetworkVO phy = phys.get(0);
|
||||||
|
|
||||||
|
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
|
||||||
|
//TODO: handle both kickstart and PING
|
||||||
|
//sc.addAnd(sc.getEntity().getPodId(), Op.EQ, vm.getPodIdToDeployIn());
|
||||||
|
sc.addAnd(sc.getEntity().getPhysicalNetworkId(), Op.EQ, phy.getId());
|
||||||
|
BaremetalPxeVO pxeVo = sc.find();
|
||||||
|
if (pxeVo == null) {
|
||||||
|
throw new CloudRuntimeException("No PXE server found in pod: " + vm.getPodIdToDeployIn() + ", you need to add it before starting VM");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Answer ans = _agentMgr.send(pxeVo.getHostId(), cmd);
|
||||||
|
if (!ans.getResult()) {
|
||||||
|
s_logger.debug(String.format("Add userdata to vm:%s failed because %s", vm.getInstanceName(), ans.getDetails()));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug(String.format("Add userdata to vm:%s failed", vm.getInstanceName()), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Class<?>> getCommands() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
|
||||||
|
import com.cloud.serializer.Param;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class BaremetalPxePingResponse extends BaremetalPxeResponse {
|
||||||
|
@SerializedName(ApiConstants.PING_STORAGE_SERVER_IP) @Param(description="PING storage server ip")
|
||||||
|
private String pingStorageServerIp;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.PING_DIR) @Param(description="Root directory on PING storage server")
|
||||||
|
private String pingDir;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.TFTP_DIR) @Param(description="Tftp root directory of PXE server")
|
||||||
|
private String tftpDir;
|
||||||
|
|
||||||
|
public String getPingStorageServerIp() {
|
||||||
|
return pingStorageServerIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPingStorageServerIp(String pingStorageServerIp) {
|
||||||
|
this.pingStorageServerIp = pingStorageServerIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPingDir() {
|
||||||
|
return pingDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPingDir(String pingDir) {
|
||||||
|
this.pingDir = pingDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTftpDir() {
|
||||||
|
return tftpDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTftpDir(String tftpDir) {
|
||||||
|
this.tftpDir = tftpDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,157 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.IAgentControl;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
import com.cloud.agent.api.ReadyAnswer;
|
||||||
|
import com.cloud.agent.api.ReadyCommand;
|
||||||
|
import com.cloud.agent.api.StartupCommand;
|
||||||
|
import com.cloud.agent.api.StartupPxeServerCommand;
|
||||||
|
import com.cloud.host.Host.Type;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
|
public class BaremetalPxeResourceBase implements ServerResource {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(BaremetalPxeResourceBase.class);
|
||||||
|
String _name;
|
||||||
|
String _guid;
|
||||||
|
String _username;
|
||||||
|
String _password;
|
||||||
|
String _ip;
|
||||||
|
String _zoneId;
|
||||||
|
String _podId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
_name = name;
|
||||||
|
_guid = (String)params.get(BaremetalPxeService.PXE_PARAM_GUID);
|
||||||
|
_ip = (String)params.get(BaremetalPxeService.PXE_PARAM_IP);
|
||||||
|
_username = (String)params.get(BaremetalPxeService.PXE_PARAM_USERNAME);
|
||||||
|
_password = (String)params.get(BaremetalPxeService.PXE_PARAM_PASSWORD);
|
||||||
|
_zoneId = (String)params.get(BaremetalPxeService.PXE_PARAM_ZONE);
|
||||||
|
_podId = (String)params.get(BaremetalPxeService.PXE_PARAM_POD);
|
||||||
|
|
||||||
|
if (_guid == null) {
|
||||||
|
throw new ConfigurationException("No Guid specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zoneId == null) {
|
||||||
|
throw new ConfigurationException("No Zone specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ip == null) {
|
||||||
|
throw new ConfigurationException("No IP specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_username == null) {
|
||||||
|
throw new ConfigurationException("No username specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_password == null) {
|
||||||
|
throw new ConfigurationException("No password specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ReadyAnswer execute(ReadyCommand cmd) {
|
||||||
|
s_logger.debug("Pxe resource " + _name + " is ready");
|
||||||
|
return new ReadyAnswer(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.BaremetalPxe;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StartupCommand[] initialize() {
|
||||||
|
StartupPxeServerCommand cmd = new StartupPxeServerCommand();
|
||||||
|
cmd.setName(_name);
|
||||||
|
cmd.setDataCenter(_zoneId);
|
||||||
|
cmd.setPod(_podId);
|
||||||
|
cmd.setPrivateIpAddress(_ip);
|
||||||
|
cmd.setStorageIpAddress("");
|
||||||
|
cmd.setVersion("");
|
||||||
|
cmd.setGuid(_guid);
|
||||||
|
return new StartupCommand[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingCommand getCurrentStatus(long id) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnected() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IAgentControl getAgentControl() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAgentControl(IAgentControl agentControl) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer executeRequest(Command cmd) {
|
||||||
|
if (cmd instanceof ReadyCommand) {
|
||||||
|
return execute((ReadyCommand) cmd);
|
||||||
|
} else {
|
||||||
|
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.BaseResponse;
|
||||||
|
|
||||||
|
import com.cloud.serializer.Param;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class BaremetalPxeResponse extends BaseResponse {
|
||||||
|
@SerializedName(ApiConstants.ID) @Param(description="device id of ")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this external dhcp device belongs to")
|
||||||
|
private String physicalNetworkId;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
|
||||||
|
private String providerId;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.POD_ID) @Param(description="pod id where the device is in")
|
||||||
|
private String podId;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhysicalNetworkId() {
|
||||||
|
return physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhysicalNetworkId(String physicalNetworkId) {
|
||||||
|
this.physicalNetworkId = physicalNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProviderId() {
|
||||||
|
return providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProviderId(String providerId) {
|
||||||
|
this.providerId = providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPodId() {
|
||||||
|
return podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPodId(String podId) {
|
||||||
|
this.podId = podId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
// Apache License, Version 2.0 (the "License"); you may not use this
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 04/03/2012
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.database.BaremetalPxeVO;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.component.Adapter;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
public interface BaremetalPxeService extends Adapter {
|
||||||
|
|
||||||
|
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile nic, DeployDestination dest, ReservationContext context);
|
||||||
|
|
||||||
|
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
|
||||||
|
|
||||||
|
BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd);
|
||||||
|
|
||||||
|
BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo);
|
||||||
|
|
||||||
|
List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
|
||||||
|
|
||||||
|
public static final String PXE_PARAM_TYPE = "type";
|
||||||
|
public static final String PXE_PARAM_ZONE = "zone";
|
||||||
|
public static final String PXE_PARAM_POD = "pod";
|
||||||
|
public static final String PXE_PARAM_IP = "ip";
|
||||||
|
public static final String PXE_PARAM_GUID = "guid";
|
||||||
|
public static final String PXE_PARAM_TFTP_DIR = "tftpDir";
|
||||||
|
public static final String PXE_PARAM_USERNAME = "username";
|
||||||
|
public static final String PXE_PARAM_PASSWORD = "password";
|
||||||
|
public static final String PXE_PARAM_PING_STORAGE_SERVER_IP = "pingStorageServerIp";
|
||||||
|
public static final String PXE_PARAM_PING_ROOT_DIR = "pingDir";
|
||||||
|
public static final String PXE_PARAM_PING_STORAGE_SERVER_USERNAME = "pingStorageServerUserName";
|
||||||
|
public static final String PXE_PARAM_PING_STORAGE_SERVER_PASSWORD = "pingStorageServerPassword";
|
||||||
|
}
|
||||||
@ -0,0 +1,169 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import com.cloud.baremetal.manager.BaremetalManager;
|
||||||
|
import com.cloud.dc.DataCenter.NetworkType;
|
||||||
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.Network.Capability;
|
||||||
|
import com.cloud.network.Network.GuestType;
|
||||||
|
import com.cloud.network.Network.Provider;
|
||||||
|
import com.cloud.network.Network.Service;
|
||||||
|
import com.cloud.network.Networks.TrafficType;
|
||||||
|
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||||
|
import com.cloud.network.element.IpDeployer;
|
||||||
|
import com.cloud.network.element.NetworkElement;
|
||||||
|
import com.cloud.network.element.UserDataServiceProvider;
|
||||||
|
import com.cloud.offering.NetworkOffering;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.component.AdapterBase;
|
||||||
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.vm.NicProfile;
|
||||||
|
import com.cloud.vm.ReservationContext;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
|
@Local(value = NetworkElement.class)
|
||||||
|
public class BaremetalUserdataElement extends AdapterBase implements NetworkElement, UserDataServiceProvider {
|
||||||
|
private static Map<Service, Map<Capability, String>> capabilities;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BaremetalPxeManager pxeMgr;
|
||||||
|
|
||||||
|
static {
|
||||||
|
capabilities = new HashMap<Service, Map<Capability, String>>();
|
||||||
|
capabilities.put(Service.UserData, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canHandle(DeployDestination dest) {
|
||||||
|
if (dest.getDataCenter().getNetworkType() == NetworkType.Basic && dest.getHost().getHypervisorType() == HypervisorType.BareMetal) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
|
||||||
|
ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
||||||
|
if (!canHandle(dest)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.getType() != VirtualMachine.Type.User) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pxeMgr.addUserData(nic, (VirtualMachineProfile<UserVm>) vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Service, Map<Capability, String>> getCapabilities() {
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Provider getProvider() {
|
||||||
|
return BaremetalPxeManager.BAREMETAL_USERDATA_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
|
||||||
|
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
|
||||||
|
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
|
||||||
|
throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady(PhysicalNetworkServiceProvider provider) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
|
||||||
|
ResourceUnavailableException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEnableIndividualServices() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm)
|
||||||
|
throws ResourceUnavailableException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verifyServicesCombination(Set<Service> services) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.ApiErrorCode;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd.CommandType;
|
||||||
|
import org.apache.cloudstack.api.BaseListCmd;
|
||||||
|
import org.apache.cloudstack.api.Parameter;
|
||||||
|
import org.apache.cloudstack.api.PlugService;
|
||||||
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
|
import org.apache.cloudstack.api.response.ListResponse;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
|
||||||
|
public class ListBaremetalDhcpCmd extends BaseListCmd {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(ListBaremetalDhcpCmd.class);
|
||||||
|
private static final String s_name = "listexternaldhcpresponse";
|
||||||
|
@PlugService BaremetalDhcpManager _dhcpMgr;
|
||||||
|
|
||||||
|
// ///////////////////////////////////////////////////
|
||||||
|
// ////////////// API parameters /////////////////////
|
||||||
|
// ///////////////////////////////////////////////////
|
||||||
|
@Parameter(name = ApiConstants.ID, type = CommandType.LONG, description = "DHCP server device ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.POD_ID, type = CommandType.LONG, description = "Pod ID where pxe server is in")
|
||||||
|
private Long podId;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.DHCP_SERVER_TYPE, type = CommandType.STRING, description = "Type of DHCP device")
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getPodId() {
|
||||||
|
return podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPodId(Long podId) {
|
||||||
|
this.podId = podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceType() {
|
||||||
|
return deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceType(String deviceType) {
|
||||||
|
this.deviceType = deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||||
|
ResourceAllocationException, NetworkRuleConflictException {
|
||||||
|
try {
|
||||||
|
ListResponse<BaremetalDhcpResponse> response = new ListResponse<BaremetalDhcpResponse>();
|
||||||
|
List<BaremetalDhcpResponse> dhcpResponses = _dhcpMgr.listBaremetalDhcps(this);
|
||||||
|
response.setResponses(dhcpResponses);
|
||||||
|
response.setResponseName(getCommandName());
|
||||||
|
this.setResponseObject(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Exception happend while executing ListBaremetalDhcpCmd");
|
||||||
|
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCommandName() {
|
||||||
|
return s_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.ApiErrorCode;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd;
|
||||||
|
import org.apache.cloudstack.api.BaseCmd.CommandType;
|
||||||
|
import org.apache.cloudstack.api.BaseListCmd;
|
||||||
|
import org.apache.cloudstack.api.Parameter;
|
||||||
|
import org.apache.cloudstack.api.PlugService;
|
||||||
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
|
import org.apache.cloudstack.api.response.ListResponse;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
|
||||||
|
public class ListBaremetalPxePingServersCmd extends BaseListCmd {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(ListBaremetalPxePingServersCmd.class);
|
||||||
|
private static final String s_name = "listpingpxeserverresponse";
|
||||||
|
|
||||||
|
@PlugService
|
||||||
|
BaremetalPxeManager _pxeMgr;
|
||||||
|
// ///////////////////////////////////////////////////
|
||||||
|
// ////////////// API parameters /////////////////////
|
||||||
|
// ///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ID, type = CommandType.LONG, description = "Ping pxe server device ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.POD_ID, type = CommandType.LONG, description = "Pod ID where pxe server is in")
|
||||||
|
private Long podId;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getPodId() {
|
||||||
|
return podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPodId(Long podId) {
|
||||||
|
this.podId = podId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||||
|
ResourceAllocationException, NetworkRuleConflictException {
|
||||||
|
try {
|
||||||
|
ListResponse<BaremetalPxeResponse> response = new ListResponse<BaremetalPxeResponse>();
|
||||||
|
List<BaremetalPxeResponse> pxeResponses = _pxeMgr.listPxeServers(this);
|
||||||
|
response.setResponses(pxeResponses);
|
||||||
|
response.setResponseName(getCommandName());
|
||||||
|
this.setResponseObject(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Exception happend while executing ListPingPxeServersCmd" ,e);
|
||||||
|
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCommandName() {
|
||||||
|
return s_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Automatically generated by addcopyright.py at 01/29/2013
|
||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
|
||||||
|
public class PrepareKickstartPxeServerCommand extends Command {
|
||||||
|
private String ksFile;
|
||||||
|
private String repo;
|
||||||
|
private String templateUuid;
|
||||||
|
private String mac;
|
||||||
|
private String ksDevice;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean executeInSequence() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKsFile() {
|
||||||
|
return ksFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKsFile(String ksFile) {
|
||||||
|
this.ksFile = ksFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRepo() {
|
||||||
|
return repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepo(String repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemplateUuid() {
|
||||||
|
return templateUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplateUuid(String templateUuid) {
|
||||||
|
this.templateUuid = templateUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMac() {
|
||||||
|
return mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMac(String mac) {
|
||||||
|
this.mac = mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKsDevice() {
|
||||||
|
return ksDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKsDevice(String ksDevice) {
|
||||||
|
this.ksDevice = ksDevice;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.cloud.baremetal.networkservice;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.SecurityGroupRulesCmd;
|
||||||
|
|
||||||
|
public class SecurityGroupHttpClient {
|
||||||
|
|
||||||
|
public Answer call(String guestIp, SecurityGroupRulesCmd cmd) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean echo(String ip, long millis, long millis2) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -42,6 +42,7 @@
|
|||||||
<module>hypervisors/xen</module>
|
<module>hypervisors/xen</module>
|
||||||
<module>hypervisors/kvm</module>
|
<module>hypervisors/kvm</module>
|
||||||
<module>hypervisors/simulator</module>
|
<module>hypervisors/simulator</module>
|
||||||
|
<module>hypervisors/baremetal</module>
|
||||||
<module>network-elements/elastic-loadbalancer</module>
|
<module>network-elements/elastic-loadbalancer</module>
|
||||||
<module>network-elements/ovs</module>
|
<module>network-elements/ovs</module>
|
||||||
<module>network-elements/nicira-nvp</module>
|
<module>network-elements/nicira-nvp</module>
|
||||||
|
|||||||
@ -358,7 +358,13 @@ public enum Config {
|
|||||||
DetailBatchQuerySize("Advanced", ManagementServer.class, Integer.class, "detail.batch.query.size", "2000", "Default entity detail batch query size for listing", null),
|
DetailBatchQuerySize("Advanced", ManagementServer.class, Integer.class, "detail.batch.query.size", "2000", "Default entity detail batch query size for listing", null),
|
||||||
|
|
||||||
ConcurrentSnapshotsThresholdPerHost("Advanced", ManagementServer.class, Long.class, "concurrent.snapshots.threshold.perhost",
|
ConcurrentSnapshotsThresholdPerHost("Advanced", ManagementServer.class, Long.class, "concurrent.snapshots.threshold.perhost",
|
||||||
null, "Limits number of snapshots that can be handled by the host concurrently; default is NULL - unlimited", null);
|
null, "Limits number of snapshots that can be handled by the host concurrently; default is NULL - unlimited", null),
|
||||||
|
|
||||||
|
ExternalBaremetalSystemUrl("Advanced", ManagementServer.class, String.class, "external.baremetal.system.url", null, "url of external baremetal system that CloudStack will talk to", null),
|
||||||
|
ExternalBaremetalResourceClassName("Advanced", ManagementServer.class, String.class, "external,baremetal.resource.classname", null, "class name for handling external baremetal resource", null),
|
||||||
|
EnableBaremetalSecurityGroupAgentEcho("Advanced", ManagementServer.class, Boolean.class, "enable.baremetal.securitygroup.agent.echo", "false", "After starting provision process, periodcially echo security agent installed in the template. Treat provisioning as success only if echo successfully", null),
|
||||||
|
IntervalToEchoBaremetalSecurityGroupAgent("Advanced", ManagementServer.class, Integer.class, "interval.baremetal.securitygroup.agent.echo", "10", "Interval to echo baremetal security group agent, in seconds", null),
|
||||||
|
TimeoutToEchoBaremetalSecurityGroupAgent("Advanced", ManagementServer.class, Integer.class, "timeout.baremetal.securitygroup.agent.echo", "3600", "Timeout to echo baremetal security group agent, in seconds, the provisioning process will be treated as a failure", null);
|
||||||
|
|
||||||
private final String _category;
|
private final String _category;
|
||||||
private final Class<?> _componentClass;
|
private final Class<?> _componentClass;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user