diff -r a477397bba8b -r c9748fcc32de components/openstack/neutron/files/agent/solaris/interface.py --- a/components/openstack/neutron/files/agent/solaris/interface.py Mon May 16 14:46:20 2016 +0200 +++ b/components/openstack/neutron/files/agent/solaris/interface.py Fri May 20 17:42:29 2016 -0400 @@ -14,18 +14,34 @@ # # @author: Girish Moodalbail, Oracle, Inc. -from oslo.config import cfg + +import rad.client as radcli +import rad.connect as radcon +import rad.bindings.com.oracle.solaris.rad.evscntl_1 as evsbind + +from oslo_config import cfg +from oslo_log import log as logging from neutron.agent.linux import utils from neutron.agent.solaris import net_lib +from neutron.common import exceptions +LOG = logging.getLogger(__name__) + OPTS = [ cfg.StrOpt('evs_controller', default='ssh://evsuser@localhost', help=_("An URI that specifies an EVS controller")) ] +class EVSControllerError(exceptions.NeutronException): + message = _("EVS controller: %(errmsg)s") + + def __init__(self, evs_errmsg): + super(EVSControllerError, self).__init__(errmsg=evs_errmsg) + + class SolarisVNICDriver(object): """Driver used to manage Solaris EVS VNICs. @@ -54,6 +70,9 @@ raise SystemExit(_("'user' and 'hostname' need to be specified " "for evs_controller")) + # save the user and EVS controller info + self.uh = uh + self._rad_connection = None # set the controller property for this host cmd = ['/usr/sbin/evsadm', 'show-prop', '-co', 'value', '-p', 'controller'] @@ -63,17 +82,31 @@ 'controller=%s' % (conf.evs_controller)] utils.execute(cmd) + @property + def rad_connection(self): + if (self._rad_connection is not None and + self._rad_connection._closed is None): + return self._rad_connection + + LOG.debug(_("Connecting to EVS Controller at %s as %s") % + (self.uh[1], self.uh[0])) + + self._rad_connection = radcon.connect_ssh(self.uh[1], user=self.uh[0]) + return self._rad_connection + def fini_l3(self, device_name): ipif = net_lib.IPInterface(device_name) ipif.delete_ip() - def init_l3(self, device_name, ip_cidrs): + def init_l3(self, device_name, ip_cidrs, addrconf=False): """Set the L3 settings for the interface using data from the port. ip_cidrs: list of 'X.X.X.X/YY' strings """ ipif = net_lib.IPInterface(device_name) for ip_cidr in ip_cidrs: ipif.create_address(ip_cidr) + if addrconf: + ipif.create_addrconf() # TODO(gmoodalb): - probably take PREFIX?? for L3 def get_device_name(self, port): @@ -86,27 +119,42 @@ namespace=None, prefix=None, protection=False): """Plug in the interface.""" - evs_vport = ('%s/%s') % (network_id, port_id) - dl = net_lib.Datalink(datalink_name) + try: + evsc = self.rad_connection.get_object(evsbind.EVSController()) + vports_info = evsc.getVPortInfo("vport=%s" % (port_id)) + if vports_info: + vport_info = vports_info[0] + # This is to handle HA when the 1st DHCP/L3 agent is down and + # the second DHCP/L3 agent tries to connect its VNIC to EVS, we + # will end up in "vport in use" error. So, we need to reset the + # vport before we connect the VNIC to EVS. + if vport_info.status == evsbind.VPortStatus.USED: + LOG.debug(_("Retrieving EVS: %s"), vport_info.evsuuid) + pat = radcli.ADRGlobPattern({'uuid': network_id, + 'tenant': tenant_id}) + evs_objs = self.rad_connection.list_objects(evsbind.EVS(), + pat) + if evs_objs: + evs = self.rad_connection.get_object(evs_objs[0]) + evs.resetVPort(port_id, "force=yes") - # This is to handle HA when the 1st DHCP/L3 agent is down and - # the second DHCP/L3 agent tries to connect its VNIC to EVS, we will - # end up in "vport in use" error. So, we need to reset the vport - # before we connect the VNIC to EVS. - cmd = ['/usr/sbin/evsadm', 'show-vport', '-f', - 'vport=%s' % port_id, '-co', 'evs,vport,status'] - stdout = utils.execute(cmd) - evsname, vportname, status = stdout.strip().split(':') - if status == 'used': - cmd = ['/usr/sbin/evsadm', 'reset-vport', '-T', tenant_id, - '%s/%s' % (evsname, vportname)] - utils.execute(cmd) + if not protection: + LOG.debug(_("Retrieving VPort: %s"), port_id) + pat = radcli.ADRGlobPattern({'uuid': port_id, + 'tenant': tenant_id, + 'evsuuid': network_id}) + vport_objs = self.rad_connection.list_objects( + evsbind.VPort(), pat) + if vport_objs: + vport = self.rad_connection.get_object(vport_objs[0]) + vport.setProperty("protection=none") + except radcli.ObjectError as oe: + raise EVSControllerError(oe.get_payload().errmsg) + finally: + self.rad_connection.close() - if not protection: - cmd = ['/usr/sbin/evsadm', 'set-vportprop', '-T', tenant_id, - '-p', 'protection=none', evs_vport] - utils.execute(cmd) - + dl = net_lib.Datalink(datalink_name) + evs_vport = "%s/%s" % (network_id, port_id) dl.connect_vnic(evs_vport, tenant_id) def unplug(self, device_name, namespace=None, prefix=None):